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.

Daily log - April 16, 2009

Cucumber/Webrat with Selenium I spent most of today trying to get our Cucumber setup running on Selenium and producing the same results as plain Webrat rails mode. A few things I found out:

  • click_button, passing a label or id, doesn’t work exactly the same way with Selenium. In most cases, you can just use the plain click_button, especially if there’s only one visible button on the page. In cases where you can’t, it’s best to call Selenium directly, or cheat with the choose helper.
  • If you have post-conditions (“Then” steps) that check the validity of things in the database, make sure to include in the selenium.wait_for_page in the action before, or at the top of the post-condition step. This will make sure Selenium has finished what it’s doing before you check the database.
  • You can easily provide alternate actions inside your step definitions with simulate (for plain :rails mode) and automate (for :selenium mode). If you find you’re doing this too much, it might be better to provide separate step definition files for each mode.

I didn’t finish this last night because…

I was at an event in Chapel Hill called the “YouTube Tournament”, organized by some students at UNC SILS, where my wife is attending graduate school. (If you follow me on Twitter, that’s all those #yttour messages. No, my account wasn’t compromised.) 12 people were contestants, and played their favorite strange/funny/unique videos to be judged against their opponent at each round. Here’s a list of the ones I can remember, in no particular order (some have explicit language):

In addition to videos from the contestants, the event organizers played a few of their favorites during breaks. We saw two cheesy Toto videos, a “literalized” remake of A-ha’s “Take On Me”, and a Rickroll, but this one was my favorite non-competition video of the night.

UPDATE: Here’s some more I found by searching twitter for #yttour.

Daily log - April 15, 2009

ResponseCache on its deathbed? Last night, I started upgrading Radiant to use Rails 2.3.2. Of course, tons of specs in our suite broke, and initially nothing would even run. A large number of the specs that broke were around the ResponseCache class, which handles Radiant’s 5-minute automatic-expiring page cache. Rails 2.3 includes a number of changes that simplify ActionPack, including a rewrite of the request and response classes to use Rack. Thus it seems natural that ResponseCache broke the most. However, I had been looking at Rack::Cache a while back, and it seems it may do most of what we want, provided we return the right headers from page renders (ETag, Last-Modified, and Cache-Control come to mind), and we implement a way to manually expire the cache. This should be good work to do at the Radiant hack day next week.

More cucumber stuff If you start using the new “profiles” feature in cucumber for running your feature stories, and you want to run different modes with the rake task (say, one for bare webrat and one for Selenium), you have to specify both which profile with t.profile = 'foobar' and also clear out the default step files, t.step_files = ''. Otherwise, you’ll get the problem I was having – trying to run both bare Webrat and Selenium (huh?) because the setup files were both required.

Variety is the spice of life As a freelancer, it’s easy to want to fill up every waking moment with something that will either move your projects along or to learn something new. My work had run late today (a bad habit lately and a consequence of working with people in later time zones), so by the time I was ready for dinner I was famished, tired, and frustrated. After eating, my wife Liz encouraged me to read a book instead of messing around on my computer. I’m glad I did – I read about a quarter of The Kite Runner in one sitting and didn’t think about my computer once. Ironically, here I am finishing up my daily log on my computer.

Tax day Did you file your taxes by today? Big thanks to Jeff for doing such a great job on ours. In light of the recent “tempest in a teapot”/“astroturf” movement in anger over paying taxes, one might find it ironic that the Progressive movement that spawned the income tax came about in very similar times to these: a Gilded age where government had too little regulation over how businesses conduct themselves, much at the expense of the larger populace. Personally, I don’t mind paying my share of taxes, given a reasonable modicum of fairness.

Daily log - April 14, 2009

Cucumber win I completed the first weekly “release” of my new project today. After I merged a number of commits from our designer, I ran the Cucumber suite and the spec suite. Nothing failed in the specs, but Cucumber found a regression that was caused by a minor mis-nesting of conditionals in one template. I was able to fix the problem in mere moments, commit, push, and deploy. With our old process, that change would not likely have been found until much later. WIN!

More Cucumber win I completed converting Radiant’s integration specs over to Cucumber stories today (see github). What does this mean? One — we’ll be able to more quickly and efficiently build new features in the core that are tested top-to-bottom; and two — you will soon be able to write cucumber features in your extensions.

Don’t be so hard on yourself, it’s not you. I was reminded of Liz Gilbert’s TED presentation today. If you haven’t seen this yet, you should definitely watch it. She basically says that since the Renaissance, we have internalized the font of creativity, whereas ancient cultures viewed the “genius” (as she calls it) as other. Her point is that in doing this, we put too much pressure on the individual’s performance and set ourselves up for devastating failure. Even if you don’t believe in something supernatural or paranormal, the concept can still be useful to promote a healthy attitude toward creativity. To me, this has special relevance in the tech community lately, especially with respect to the emphasis on wanting ROCKSTAR developers/sysadmins/whatever. It’s better to get someone who consistently produces good, reliable code and can play well with others. I want to be a “Jazzer” developer.

Daily log - April 13, 2009

Inspired by Clinton Nixon, I’m going to start writing daily logs of things I’ve learned or am thinking about. Hopefully it will turn into a good habit!

Rails arcana: Don’t specify :method => :get as an option to a custom route if you want to filter by HTTP method. Use :conditions => {:method => :get}, or your controller test will complain about not having a route to that action. Personally, I think this is unintuitive, but a minor point at best.

Cucumber and Textmate: To run Cucumber features properly in TextMate, I had to modify the default bundle. First it was running ./script/cucumber.rake (why?), from which I removed .rake. I also added -r features as a command line parameter so it would require all my step definitions.

To shard or not to shard: I had an interesting discussion with James Avery and Mark Imbriaco about running multi-tenant apps and database sharding. The consensus was don’t worry about sharding at first – let database scaling issues drive the decision. Also, 37signals apps manually scope each query by account. Seems it will be a decent amount of work to implement this when my latest project is ready for more than one tenant. Luckily, we won’t have to worry about this until we prep the fall release of the software.

Iron Chefs: I was able to help Jim Van Fleet on IRC with a Chef recipe question, and we filed a feature request.

Allez cuisine!: I got some kudos from Adam Jacob for my RSpec skills — “you are an rspec pimp” — apparently because I rewrote a number of the specs he had written to be less coupled to the implementation. He wants to run a conference call soon to help new Chef contributors get up to speed with RSpec, and wants me on it to at least “call [him] on stupid stuff”. Looking forward to this!