Decorating Instance Methods of a Class

scrubyt_logo.png
I am just working on a brand new release of scRUBYt!, with the intent of bringing AJAX/javascript scraping to the masses (and other great stuff – will announce the release soon).

Scraping js-heavy pages is not that trivial, among other things because of the asynchronous nature of Javascript. Quite frequently you click on a link (or do any other action triggering an AJAX call) which inserts/fills/pops up a div on the page and you want to navigate/get some data from the new content. However, it’s hard to impossible to determine when did the browser finish displaying the new data – the easiest solution is to wait a few seconds after an AJAX update, until the data is properly loaded.

In practice this means that all scRUBYt! navigation methods (click_link, fill_textfield, check_checkbox, select_item, …) need a decorated version, which waits a given amount of time after executing the navigation step. So for example, given the original method:

def click_link(xpath) ... end

we want a decorated version:

def click_link_and_wait(xpath, seconds)
  click_link xpath #the original method
  sleep seconds if seconds > 0
end

For each and every method of the NavigationAction class.

Fortunately Ruby makes this really easy! Decorating the existing methods explicitly upon class creation:

  (instance_methods - Object.instance_methods).each do |old_method|
    define_method "#{old_method}_and_wait" do |seconds|
      send old_method ; sleep seconds
    end
  end

or implicitly, runtime:

alias_method :throw_method_missing, :method_missing

def method_missing(method_name, *args, &block)
  original_method_name = method_name.to_s[/(.+)_and_wait/,1]
  if (method_name.to_s =~ /_and_wait/) && (respond_to? original_method_name)
    self.send original_method_name ; sleep args[0]
  else
    throw_method_missing(method_name, *args, &block)
  end
end

As you can see, we are executing the decorated method only if it is defined on our class and it ends in _and_wait. In all other cases we simulate the normal method_missing_behavior.

Since we know in advance that we want to decorate all the methods of the class, the second way doesn’t make much sense in this case – it’s slower because it has to go through method_missing every time, while there are no advantages – however the technique is interesting and applicable in other scenarios (e.g. when you don’t know in advance which methods are you going to decorate – for example adding a constraint to a filter in scRUBYt! (filters are also created dynamically runtime))

Git External Dependency Management with Giternal

git_octocat.png
I Don’t want to reiterate what has already been said on this topic (I ended up in the same boat – tried more tools, didn’t really like any of them and settled for giternal).

Giternal seems to work nicely – after you get the initial roadblock out of the way. According to the README, you should install giternal with

gem install giternal

then use the _giternal_ executable to do various things.

The problem is that after installation, there is no _giternal_ executable – the problem is that gem installs version 0.0.1, which doesn’t have it. You have to get the sources from git and set it up yourself:

git clone git://github.com/pat-maddox/giternal.git
cd giternal
sudo ruby setup.rb

and you are good to go.

Hope this saves someone a few minutes.

Ruby Quiz: Unit Conversions

ruby_quiz.png I decided to join Ruby Quiz for the first time ever – I am realizing that I am extremely late to jump on the RQ bandwagon – but hey, is still better later than never. I have chosen a funny moment though: it’s a quiz everyone was excited about, but almost nobody solved (2 solutions so far except mine, which is maybe the lowest number of solvers ever). So here’s the quiz:

Your task is to write a units converter script. The input to the
script must be three arguments: the quantity, the source units, and
the destination units. The first example above would be run like this:

    $ ruby convert.rb 50 miles kilometers

Or, using abbreviations:

    $ ruby convert.rb 50 mi km

Support as many units and categories of units (i.e. volume, length,
weight, etc.) as you can, along with appropriate abbreviations for
each unit.

and my solution:

require 'rubygems'
require 'cgi'
require 'scrubyt'

begin
google_converter = Scrubyt::Extractor.define do
 fetch "http://www.google.com/search?q=#{CGI::escape(ARGV[0])}+#{CGI::escape(ARGV[1])}+to+#{CGI::escape(ARGV[2])}"

 google_result "//td[@dir='ltr']" do
   final_result(/= (.+) /)
 end
end
 puts google_converter.to_hash[0][:final_result]
rescue
 puts "Sorry, even *google* can't translate that!"
end

Examples:

ex:
ruby converter.rb 10 "meter per second" "mile per hour"
22.3693629

ruby converter.rb 10 USD EUR
7.91201836

ruby converter.rb 7 "ruby gems" "python eggs"
Sorry, even *google* can't translate that!

The biggest downside of the proposed solution is that you need to be on-line. However, nowadays, when this is almost the norm, the advantages outweigh this in my opinion:

  • Support for a lot of conversions (I doubt anyone can offer a much richer database of units than google) including their abbreviations
  • Up-to-date conversions: for example currency conversion
  • Very robust error handling – outsourced to google! Hard to beat that…

Why Buying a Mac for (Rails) Developers is a Good Idea

“It’s better to be a pirate than to join the Navy” (Steve Jobs)




This post was inspired by the last part of Jim Neath’s article on speeding up Rails development, titled “Seriously, Just Buy a Fucking Mac”. Some commenters insisted that you can do just as well on other systems (Ubuntu, in particular). In three short words, I don’t agree. In my opinion Ubuntu is a valid alternative but it comes in at second place, and the gap between the 1st and 2nd position is significant. Why?

Software

Some people, when it comes to a good PC vs. Mac fight, start to brag about the hardware – it’s overpriced, and not that much better, and my high end PC notebook is better because … etc. Because they most probably never ever used a Mac for a longer period, they don’t know that the real speed gain/ease || joy of use comes from the software (though it doesn’t hurt that there are no hardware conflicts, evar, no matter how much do you upgrade, no messing around with wifi/mic/video cards/you name it and the quality is top-notch etc.) No. The real secret sauce is the software:

The essential stuff

ruby_logo.pngrails.png

Ruby and Rails – I have spent a few years on Ubuntu from warty to gutsy, and though it was improving from release to release, when I bought an MBP a year ago, the difference was shocking. C’mon, installing Ruby and the whole Rails stack on ubuntu is still a considerable pain, whereas OS X ships with ruby/rails by default.

text_mate.png

A powerful editor – TextMate the best editor ever invented, hands down – mainly when beefed up with Ruby/Rails bundles (the ‘standard’ ones, as well as others like RubyAMP). No windows or linux editor comes even close – though this is hard to believe unless you tried TextMate for more than 5 minutes.
I have been drooling when I was on Ubuntu and checked out screencasts like peepcode Textmate 2 for rails – fortunately I bought a Mac, watched the video and using Textmate ever since, so the drooling stopped.

sequel_pro.png

An intuitive SQL GUI – CocoaMySQL/Sequel Pro. Sorry guys, MyPHPAdmin doesn’t count. Neither does mysql-query-browser, which is the windows 3.11 of the SQL GUIs IMHO. Sequel Pro rocks!

Other niceties

skitch.png

Skitch is something I had no clue I needed, but now I couldn’t live without it! “Skitch.com is a webservice that works hand in hand with our application Skitch to give you 1-click
uploading of images for fast and fun image sharing.”
. Doesn’t sound that mind-numbing, but try it once and become addicted forever.

dropbox.png

Dropbox is a kickass utility to store, sync and share your files online. The best part is that it actually works – it’s not some half-assed solution, but a really working, beautifully executed powerful tool for sharing your stuff.

cyberduck.png

Cyberduck is an an incredibly useful FTP, SFTP, WebDAV & Amazon S3 Browser for Mac OS X. Really missed something similar under Ubuntu.

css_edit.png

CSSEdit – I was really missing a good CSS editor under Linux – the existing ones didn’t even come close to CSSEdit. CSSEdit’s intuitive approach to style sheets and powerful previewing features will make you deliver awesome standards-based sites in no time!

mars_edit.png

MarsEdit is a desktop blog editor, so you can write a blog without giving up the comforts of your Mac. Since I am using MarsEdit, blogging has become a whole new experience – instead of a clumsy web-interface which requires me to be on-line I can focus on blogging actually!

Once you get productive with these extremely powerful tools (and I didn’t even mention the standard built in stuff like Spotlight, iCal, iChat, Time Machine, …) your development time will be greatly reduced compared to that on an Ubuntu/Windows/… machine. For realz!

Everyone and Their Dog is on a Mac

So… why should I keep up with the Joneses – did the me-too club become popular recently? Isn’t Apple’s mantra ‘think different’? Why join the ‘cool kids’?

Valid questions – however, everyone else being on macs also means that

  • you’ll have a much bigger chance of getting quick support on the Ruby/Rails forums/IRC – which is not always easy with Ubuntu (I am on Ubuntu Rusty Robot build R2-D2. Everything is fine, but MySQL driver doesn’t compile because I ran dist-upgrade yesterday, and now everything is jammed. All the tutorials are up to Humpty-dumpty Drake only…).
  • Easier collaboration – sharing Dropbox folders, skitch images, iCal events etc. is very-very common – of course there are other ways of sharing data/notes/collaboratively editing documents, but these Mac tools take it to a whole new level.
  • Growing Mac usage means that more goodness is on the way!

A bit of Mythbusting

  • Macs are crazy expensive
  • You can buy a mac mini starting from $599, or a pre-owned one for $350. Doesn’t sound like bank-breaking. Good PCs are not cheap either – my last DELL was about the same price as my current (almost high-end) MBP. Of course you can buy an Acer for third of the price, but well, the drop in the quality will be proportional.

  • Mac software is expensive, on linux everything is free
  • From the above list, everything essential is free, except TextMate, which is a must, no matter how much it costs. Usually free alternatives exist for almost everything, and the commercial ones are just unbelievably good.

  • You are going to deploy to a linux server, so create your app on linux too
  • While OS X is not linux based, the difference is minimal – Darwin is a POSIX compliant OS so from the Rails development perspective it doesn’t really matter. I do not have accurate data but I don’t think so it’s easier to migrate an app developed on gentoo/fedora/suse/… to an ubuntu box than to do the same for an OS X Rails app. And even deploying from Ubuntu to Ubuntu can be a pain unless the boxes contain the same version of everything etc.

  • I think you just bought a Mac because the “cool kids” did
  • So what? Does this alter the fact that working on a Mac makes you more productive/effective as described above? Not at all.

Use the Best Tool for the Job

Yeah… in other words, seriously, just buy a fucking mac. It’s the best tool when it comes to (not only) Ruby/Rails development.

Rails Rumble Observations, part II – trends in gem/plugin usage

rails_rumble.png
In part I I wrote about the hows and whys of gathering gem/plugin usage data based on Rails Rumble submitted user information, and in this part I would like to present my findings. So without further ado, here we go:

Prototype/jQuery

I already covered this in part I, but for completeness’ sake, here is the chart again:


prototype_jquery.png

It seems that jQuery is (not so) slowly replacing Prototype as the javascript framework of Rails – which is still better (from the Prototype POV) than with Merb, where jQuery is the default framework (oh yeah, I know, Merb is everything-agnostic etc. etc. but I think vast majority of merbists are using Datamapper, jQuery etc. (?)).

Skeleton Applications

Well… this chart is rather dull:


bort.png

One in every three teams used a skeleton application (which in this context can be replaced with ‘Bort’).
The sovereignity of Bort is a bit surprising given that it’s not the only player in the field by far – there are definitely others, like ThoughtBot’s suspenders, Blank by James Golick, starter-app by Pat Maddox, appstarter by Lattice Purple just to name a few.

I am not sure about the others, but the absence of suspenders from the chart has more to do with the fact that it was not yet publicly released before Rails Rumble – I am basing this claim on the fact that a lot of people used the gems/plugins which, combined together, are basically suspenders.

However, this doesn’t alter the fact that Bort is immensely popular – great stuff, Jim.

Testing Frameworks

I think there are (at least) 2 things to note here:

  1. Testing in Ruby/Rails is not considered optional even facing a very tight deadline. Even if we assume that the 49% didn’t test at all (which surely doesn’t sound too realistic – they probably just went with Test::Unit), more than half of the teams did!
  2. Though testing tools are a much debated topic nowadays, and the winner is not clear (yet) – I would guess, based on the above results there is roughly an 1:1:1 ration between Test::Unit, rspec and shoulda *currently* – there are definitely interesting alternatives to Test::Unit.


testins.png

Mocking


mocking.png

Not much to add here – though the above chart says nothing about how much people are using e.g. Mocha with rSpec (vs. using the rSpec built-in mocking tools), one thing is clear – as a stand-alone mocking framework, Mocha reigns supreme.

Exception Notification


ex_notification.png

Another point for ThoughtBot (not the last one in this list) – Hoptoad has no disadvantage compared to the more traditional Exception Notifier (if we don’t count getting an API-key, which takes about a minute) – on the upside, you get a beautiful and user friendly web GUI.

Full-text Search


full_text.png

I found the above chart interesting for two reasons:

  1. I thought that Ferret and/or acts_as_solr are still somewhat popular – it turns out they are not
  2. I also thought Thinking Sphinx is the de-facto fulltext search plugin, and didn’t know about Xapian – well, I learned something new again.

Uploading


uploading.png

ThoughtBot did it again – Paperclip is already more popular than the old-school attachment-fu. I am always a bit cautious when someone challenges the status quo (like Nokogiri vs.
Hpricot, Authlogic vs. Restful Authentication, attachment-fu vs. Paperclip etc.) but it seems Paperclip is ripe to take over. You can find some interesting tutorials here and here.

User Authentication

Another dull graph for you:


user_auth.png

I am wondering how homogenous this chart would be if Authlogic would have appeared earlier – it seems like a strong challenger (already watched by around 260 people on github) and I am sure it will take a nice slice of the pie in the future.

What’s more interesting is the openID support: more than one third of the apps offered openID authentication, and quite a few of them *solely* openID.

Misc

  • factory_girl was used to replace traditional fixtures in every 6th of the apps!
  • HAML/SASS is quite popular – used in about 20% of the applications
  • Hpricot was the only HTML/XML parser used (in 7 apps alltogerher)

What I am happy about the most is that there is still a lot of innovation going on in the Rails world – as you can see, newer and newer plugins/gems are appearing and in some (in fact, a lot of) cases are dethroning their good ol’ competitors. There is a lot of competition going on in almost every major area of Rails web development, and this is always a good thing.

Rails Rumble Observations, part I – jQuery on the Heels of Prototype

rails_rumble.png
As a Rails Rumble judge, I spent quite some time reviewing the applications and I noticed several patterns regarding the gems/plugins used during the 48-hour contest. The participants were asked to submit whatever tools they were using to build their app. With a few exceptions they complied, creating an interesting data set to observe the current trends in the Rails world.

Collecting the Data

Unfortunately it was not possible to gather the information automatically using screen scraping or other mechanical methods, since the input was varying from free text (stating details like ‘we used Rails, macs, TextMate, cocaine (the drink!)’) etc. to the output of _gem list_ – and everything in-between, not following any guideline (perhaps because none was given). So I hacked up a small app with a single form and harvested the info manually. I only collected data for the first 100 entries, for two reasons: the stuff used in the rest of the apps was pretty much the same, and mainly: the task was rather daunting 🙂

Why Does this Matter?

I believe that because of the rules (I mostly mean the 48-hour deadline) the findings are quite representative – I am sure that every team reached after the most productive/easy to use/effective tool they could grab since the deadline was tight. Rails Rumble is not about experimentation or showing off some new shiny toys, but lightning fast hacking aided by state-of-the-art gems and plugins so I think it’s safe to assume that the tools used here are pretty much the crème de la crème of the Ruby/Rails world.

Prototype vs. jQuery

In the first exhibit, I’d like to check out Prototype vs. jQuery usage. To prepare this chart, I took the extra mile and didn’t rely on the user-supplied data, but opened the pages by hand and checked the headers for Prototype/jQuery javascript includes. Here is what I have found:


prototype_jquery.png

1 team was using mootools, the rest of the cake is divided between Prototype and jQuery.
Most probably the real result is even more in favor of jQuery, I would guess well above 60% – all the teams that added jQuery to their application.html.erb were actually using it (why would they bother adding it otherwise), while this is not necessarily true for Prototype, which is included by default and maybe some teams didn’t even use it, just didn’t care to delete it (as you will learn in the next part, every 3rd team used bort, which includes the Prototype/script.aculo.us files by default).

This is not the first indicator of jQuery’s rising popularity in the Rails world – Hampton Catlin’s Ruby Survey found out the same (i.e. jQuery is more popular right now than Prototype). Merb is using jQuery by default.

Is Prototype Dead?

My favorite Austrian Ruby-hacker friend told me over lunch a few weeks ago: ‘Prototype is dead!’. I think this statement is questionable at the moment to say the least, since Prototype is still the default javascript framework of Rails and this is not likely to change anytime soon due to the fact that Prototype is heavily used by 37singnals (and probably entrenched into other older Rails-apps as well).
However, the trend seems to be that jQuery is spreading really fast, replacing Prototype in a lot of cases.

So be sure to check jQuery out (it’s dead easy to install and use it) – I immediately fell in love with it (maybe I was used to Hpricot-style CSS selectors too much?) and I am happily using it in my projects now.

The Next Episode

Which testing tools are used by the community? How about rails skeleton apps? OpenID support? exception-notifier or hoptoad? attachment_fu or paperclip? mocha or flexmock? factory-girl or traditional fixtures? Find out in the next installment!