Daily log - April 23, 2009

Application accepted. I learned how to use Javascript’s apply method today (properly). For some context, I was using LowPro awesome DOM.Builder functions to create some @option@s programmatically and insert them into a select. The only thing I thought that is exceptionally quirky about the implementation is that the last argument to a “tagFunc” appears to be an array of children. However on closer inspection, the tagFunc actually takes any number of arguments after the attributes as children, but not an array. Unfortunately, since Javascript doesn’t have Ruby’s awesome “splat” operator (*) for arrays, I had to find another way. Mozilla’s Developer Connection really helped out here. At first I was trying this:

var options = [ ]; // build some options
$select({"name": "the_select_box"}, options);

Instead, this is what worked:

var options = [ ]; // build some options
options.unshift({"name": "the_select_box"}); // put the attributes first in the array
$select.apply(this, options); // "this" is not strictly necessary in this case, "null" would work

Yay for higher-order functions! UPDATE It seems Dan has corrected this issue in the LowPro available on GitHub. I’ll be upgrading!

Daily log - April 22, 2009

And now… “How Not to be Seen” It seems although Firefox happily allows you to hide <option> tags (with style="display:none"), Safari (and WebKit) won’t hide them. Anyone know why? Am I doing something wrong? I could use <optgroup> tags in a pinch, but I’m not certain they’d help.

Is that a valid statement? Using ActiveRecord::Errors (from validations) on a non-AR class is pretty easy, one only has to implement self.human_attribute_name, which I did fairly naively thus:

  def self.human_attribute_name(name)
    name.to_s.humanize
  end

Daily log - April 21, 2009

Populate this! I added a database population script to our application today so our designer could work on styling the big Javascript control I wrote. The control relies on loading some JSON data via Ajax on page-load, and he naturally had an empty database initially. In order to quickly and easily accomplish this task, I relied on the populator and faker gems. populator is great, and really fast because it doesn’t instantiate ActiveRecord objects (which has caveats, of course), but faker is totally AWESOME. I started using it in my test factories (with factory_girl) too – it was especially helpful on things like names, where I was just giving the factory “Quentin Tarantino”. One of its best features is the ability to generate strings of numbers, which was useful for creating things like student ID numbers.

You got chocolate in my peanut butter! There was a nice talk tonight at raleigh.rb about MacRuby. It seems that Apple is pretty serious about the project and the integration with Xcode is really well done. Kevin said it’s “too clicky and draggy” and gave him nightmares about Visual Studio. In contrast, I had nightmares about doing Java AWT – building interfaces entirely with code – I welcome the clicky-and-draggy! (especially since Interface Builder does it well and without too much ceremony) Letting you hook up the interface directly to your own Ruby classes just rocks. I’m excited to see where this project goes, and maybe I’ll write a GUI app in the near future with Ruby.

Daily log - April 20, 2009

Blank regexes are evil. I’ve been working on this Javascript control that involves a number of different components, one of which is an auto-completing field. I really wasn’t satisfied with the usage pattern the auto-completer in scriptaculous provides, so I decided to roll my own. Yes a little NIH, but I estimated it would take me longer to read and understand the inner workings of their auto-completer than to write my own from scratch using TDD. Long story short, I was right, but I discovered this along the way…

I made a method on my control that creates an array of regular expressions from the field input to match against our available data by splitting the field value on spaces. A piece of data will only match and be populated into the drop-down if all regexps match. Well, at first, I didn’t cover the edge case of having a piece of text with a space at the end and nothing following. When I tried to use the control in vivo, I got the “beachball” and then the “runaway script” warning. Naturally, it was because of this:

'an '.split(/\s+/) == ['an', '']

So the last element in the split array became a regexp that was essentially empty! Naturally it matched EVERYTHING and hung the browser.

Yay competion! I completed the baseline of the control later in the day and got all the Selenium stories working too. Thus ends my trial-by-fire introduction to TDD in Javascript.

Three-day log - April 17-19, 2009

This entry will count for three days — I didn’t complete a log on Friday for various reasons, but I continued to work and learn this weekend, so you’re getting a three-fer!

Unit-testing Javascript ain’t so bad! Thanks to a little courage and a nice pair-programming session with Scotty Moon, I was able to make headway on doing TDD in Javascript – it seems, like any kind of TDD, you just have to jump in and try it. I initially chose Dr. Nic’s JsUnitTest because of its simplicity, but I feel like I may switch over to JSSpec or Screw.Unit at some point. I miss the RSpec-like syntax, but I don’t use jQuery so I was a bit uncertain about those frameworks.

One should be enough. The control I’m trying to unit-test is really a combination of 3 smaller behavior classes, with the fourth behavior being the glue between them. Naturally, to keep things separated, I wanted to create test-cases for each individual control. However, things get “interesting” when you have more than one Test.Unit.Runner in your test-page, especially with test methods that use wait(). When I figured out the separate runners were causing the problem, I collapsed them into one, and voilà, my Ajax mocks started working properly too! I’d love to have some way to run multiple suites in one file, but that’s a project for some other day.

Yes and no. At one point, I struggled with how to simulate a click on an element in a test. It seems there is no reliable, cross-browser way to do this, but I found a couple of resources that gave me some clues. For testing, it’s a necessity unless you want to have to click something every time you run your tests. Luckily, I found Dr. Nic’s add-on to JsUnitTest that adds Event.simulate (and the Ajax mocks I spoke of above). In most cases, it does the job admirably, and as a bonus it adds some nice methods to easily trigger the events if you’re using Prototype. For my case, I just call _click() on the extended element.

You’ve got issues. Github unveiled their new issue-tracker this weekend. With the move of the Radiant wiki over there, it might make sense to make our ticket system on there too. It seems very simplistic but straightforward, and I like the idea of voting for issues that you want solved. We’ll definitely be moving toward this for extensions.

Another one converted. I’m helping an acquaintance who is working on a Rails app by doing weekly code-reviews for him. Because he hasn’t fully drunk the testing Kool-Aid yet, it’s been difficult to convince him to start building a test-suite (“What’s the point? I don’t get it.”). However, this weekend I think I finally got him to take a sip! I wrote an extensive email about some refactorings I wanted to suggest and ended it by pointing out how the design patterns I employed were borne out of experiences doing TDD: small methods with clear purpose, limiting functional side-effects (or keeping them explicit), appropriate assignment of responsibility, making domain objects more informative about themselves. I also explained the purpose of Cucumber: identifying the business value first, then defining the feature. In the end, he tried Cucumber and seemed to like it! WIN. Take heed young Padawans, do not build features that have no business value. They will cost you much more in the long run.