FireWatir and AJAX

Posted 3 days ago

I’ve been working on building some automated testing for a single page, AJAX heavy application. One main view with lots of lightboxes, partial page updates, etc. I wanted to test the application using FireWatir, but ran into what a lot of other people run into: Watir and FireWatir do not wait on AJAX requests to finish before continuing execution. So, if you wrote the following code:


  $ff.goto("www.yourajaxyapp.com")
  $ff.elements_by_xpath("//div[@id='test']").first.click
  $ff.elements_by_xpath("//div[@id='test2']").first.click

If test2 is created by clicking on div#test’s anchor, test2 will not exist and FireWatir will explode and exit. I wrote this really simple block that helps make these kinds of things happen less:


  def ajax_handler(xpath, &block)
    captured_block = $ff.elements_by_xpath(xpath)
    until $ff.elements_by_xpath(xpath) != captured_block
      sleep 1
    end
    yield
  end

  def after_tab_updates(&block)
    ajax_handler("//tr[@id='tabs_to_monitor']", &block)
  end

This handler captures the content of the xpath you want to observe, and then waits for that block to update before executing the code inside the block. This way, no arbitrary waiting (like using sleep 5 and hoping the request is done). Then, you use is like this:


  $ff = Firefox.new
  $ff.goto("www.yourajaxyapp.com")
  $ff.elements_by_path("//tr[@id='blah']").first.click
  after_tab_updates do
    $ff.elements_by_xpath("//tr[@id='inside_of_tabs']").first.click
  end

This way you’ll be sure to know that the page is loaded before your next request fires.

If you have a better way, let me know, but I couldn’t find a good existing solution to this.

I remember in early 2007 reading Chris Wanstrath’s excellent post Vendor Everything.

The idea behind “Vendor Everything” is to DRY up your development environment, and prevent external dependencies from slowing down your development process. I think, as a contractor, this is an excellent idea. Generally, you are in control of the version control system and you may find yourself interfacing with people in different timezones who aren’t always religious about reading their e-mail or being on IM regularly.

Much like anything else, sometimes you have to know when to follow advice and when to stray from the golden path. “Vendor Everything” is one of those things that works great in certain situations, and not so much in others.

The article hit me especially hard because I was in the tail end of working for a company that made extensive use of subversion externals, long before piston existed or most people even knew svn externals existed. We were struggling to keep our Rails applications synchronized between branches and releases (two to three times a week for nearly a year), and finding the “Vendor Everything” concept to be a headache.

Fast forward a year and a half, and I am getting ready to leave another company. We initially used Subversion, and flirted with the idea of using Piston to maintain the loads of plugins we would ultimately use. About 3 months in, everything changed and the company went in a different direction, buying Perforce and requiring all projects be immediately moved to it. If you’ve ever used Perforce, it doesn’t lend itself much to the “Vendor Everything” mind set, and I’d imagine a tool such as Piston does not exist for Perforce (I could be totally wrong).

After using Merb for a while, and with Rails 2.1 coming out with gem dependencies, I’m liking the idea of Geming everything. Rails has some holes in it that don’t make things easy (Rake tasks are not automatically loaded from gems, for example), but for the most part the process is very straightforward and really makes a lot of sense.

Plugins to me were always second class citizens; they weren’t really gems, and we created external, tool dependent mechanisms to version them, when Rubygems already had a built-in mechanism to deal with versioning. Plugins still don’t have a dependency mechanism, so one plugin cannot state which other plugins it depends on to run, although Gems have supported this for a long time. Plus, what happens when you want to use a plugin outside of Rails? It becomes a gem anyways. Let’s just end the madness and make it a gem to begin with.

I will be speaking at the NH.rb tomorrow about Merb, and my adventures in taking some Rails code I had written and converting it to run on Merb. If you’re in the area, stop by and we can have a great conversation about it. Check out the NH.rb Upcoming meetings page for more information.

RailsConf 2008 Final day highlights

Posted about 1 month ago

The final day of RailsConf! I have to admit, it was fun, but at the end, you just really want to get home.

The first talk I went to was Neal Ford’s Ruby design patterns, which was good. It introduced me to a few Ruby modules I’ve never heard of before. Mixology and the Interface switcher. I also liked the way he did a simple demonstration of DSLs.

After that, I went to Ezra’s scaling Ruby talk. Ezra introduced Vertebra, which is an XMPP based way of managing multiple servers, or potentially doing other sorts of distributed operations. I enjoyed listening to Ezra’s talk, although if I knew it was about XMPP and server maintenance, I probably would have went to something else.

I went to the talk about Dtrace, because DTrace interests me as a way of monitor Rails applications in ways that does not involve gdb or switching to JRuby. Not that there aren’t other ways, but you know. My primary development environment is also a Mac, which means I have access to Dtrace locally.

After that, it was Chad Pytel of Thoughtbot’s talk, and I really wanted to record his talk and just show it to the developers I work with. It was a great explanation of how to do the right thing with your models and controllers, and gave some really good real-world advice on cleaning up code and being more DRY. It really summed up what makes Rails a great framework, and the Rails community a good community.

The conference concluded with a panel by the four main core developers, and I was surprised that no one asked them what the roadmap was to making Rails thread-safe. There was also a conversation about ActionWebService, which is something the company I work for uses on a daily basis. A lot of other interesting questions about things like ActiveResource and other things.

I had a good time at the conference and met a lot of people in person for the first time. I heard rumor that next year’s conference will be in Las Vegas, so I can get married next year and do a bit of Rails at the same time. Now that’s efficient!

RailsConf 2008 day 2 highlights

Posted about 1 month ago

Day 2 started with a talk by Jeremy Kemper about some of the new features of Rails 2.1, and also about some of the efforts of the core team to do cleanup in Rails. At the end of his talk, he announced the release of Rails 2.1 today. Although I won’t go into an exhaustive look at it, this was some of the highlights:

  • better Timezone support – config.time_zone
  • nice new rake tasks: rake db:create, rake db:rollback
  • better built-in support for memcache-client
  • gem dependencies
  • improved migrations (no more 001, it’s datetime stamp based)
  • named scopes
  • dirty flag on attributes
  • partial updates
  • smarter :include

I’m sure there’s much more, but that was the gist of it.

After that, I went to a talk by Aaron Batallion about ESI. The information in the talk was really excellent, and it left me wanting to build a site using mongrel-esi/memcached and using FragmentFu. Basically, ESI is a way of doing caching, but unlike something like page caching, ESI can be done on a component by component basis. Very cool stuff. Aaron used it at Revolution Health which I tracked closely while I was at Eons.

I was really disappointed the talks last year about REST, and I was really hoping Ben Scofield would change my mind this year at his “Advanced” RESTful Rails. Unfortunately, a fair bit of the talk was used to explain what the term REST is, and references to Roy Fielding’s dissertation. There was a bit of code, but nothing that I would consider too advanced. Please don’t explain REST in an “advanced “RESTful talk with less than an hour of time.

I spent most of the afternoon listen to people tell me how to test/specs. Dan Manges and Zak Tamsen gave an interesting talk about testing, and had a few interesting tidbits (such as DeepTest), unit_record, and some other things.

After that, I listened to David Chelimsky talk about RSpec’s story runner, and his talk was really excellent. I left really wanting to use RSpec story runner (although I think it’s syntax is a bit too complicated and verbose).

The Keynote of the night was by Kent Beck, who is really an amazing individual. It’s hard not to respect his technical contributions, but I was also impressed at the breadth of interesting things he knew about, and his thoughtful responses to questions. He told three great stories that, in a non-boasting manner reminded us of some of the great ideas that we use today, such as TDD/BDD, Agile/XP, and testing in general.

There was a short update by Chad Fowler that mentioned that the most popular sessions of the conference will be re-created tomorrow, in case people missed them. I’m hoping to make it to Chris Wanstrath’s and Yehuda Katz’s talk, as I missed them the first time.