Ruby Programming

A Puzzle for Polite Ruby Programmers

I really enjoyed Jim Weirich’s session on polite programming at the Scottish Ruby Conference. He covered a problem that’s been vexing me for some time, about avoiding the use of method aliasing, by using inheritance instead. Unfortunately, his suggested solution didn’t tell me anything I hadn’t already tried. I still think this must be possible, but that I just don’t know quite enough about Ruby to be able to achieve it. Maybe you do?

Here’s the puzzle:

https://gist.github.com/912504

Can you solve it?

Ruby Programming

Comments (2)

Permalink

Two Truths I’ve Learned About Writing Clean Rails Apps

In summary:

  • Implement every feature without javascript first, add javascript as a progressive enhancement
  • Stick to REST. Always.

Now I’m as suspicious of absolute rules as you probably are, but these two have served me extremely well in keeping my Rails code clean and easy to maintain. I’m happy to push the boat out and call them truths, my truths anyway.

Let me explain.

Progressive Enhancement

When I first started at Songkick, Cucumber was just emerging and webrat was the new kid on the testing block. Although using Selenium for full-stack javascript testing was possible with webrat, it wasn’t easy and we quickly made a decision: we would build the first iteration of every feature to work without javascript. This was mainly driven by pragmatism: we could easily use webrat to test the app through Rails integration testing stack, and these tests ran quickly rather than waiting for a browser to start up.

What happened surprised us. We would receive fancy designs from our designers which could only be implemented with fairly complex javascript. Because of our rule, we had to figure out how to deliver the same behaviour using basic HTTP posts and gets of forms and URLs. This required us to simplify the designs for our first iteration. We got a little push-back at first but we were a tight team and the designers quickly caught on. Especially when we started shipping these iteration one features quickly and reliably. And funnily enough, it turned out that often these simple HTTP-only versions of the features were actually fine, and the designers decided we should move onto other stuff, instead of building all that complex javascript that had been implied by their earlier designs.

So this rule had helped us to do the simple thing. We shipped features and moved on.

When we did have to add javascript, we added it on top of the existing working HTTP-only implementation, and we got another surprise: it was easy! Nearly every time, because we’d built the server-side infrastructure to a clean, standard pattern, the javascript we needed was clean and simple to write.

Which leads me to my next truth…

Stick to REST. Always.

I’ve always felt a little uncomfortable with Rails’ controllers. They violate the Single Responsibility Principle for me. I’d prefer a pattern where I had a separate Request class for each action, rather than a few largely unrelated methods on the same controller class. But Rails is there and there’s a lot else to like, so let’s not get into that.

We all know it’s a bad idea to let our controllers bloat and something I’ve been enjoying greatly lately is Jose Valim‘s Inherited Resources. By sticking to this pattern, you push all the logic into your domain model, and keep the controllers focussed on what they need to do: handling web requests.

You end up with more controllers, and more models too. You create model objects that — Gosh! — don’t represent database tables, but represent other domain concepts instead. Altogether though, you end up with smaller, more focussed classes that are easier to test and easier to read and understand.

Ruby Programming

Comments (3)

Permalink

Using Capybara with RSpec Outside Cucumber

If you want to try using Capybara for browser automation on it’s own, here’s a simple script to get you started:

require 'rubygems'
 
require 'capybara'
require 'capybara/dsl'
 
Capybara.default_driver = :selenium
Capybara.app_host = "http://www.google.com"
 
require "rspec/expectations"
class Google
  include Capybara
  include RSpec::Matchers
 
  def search_for(text)
    visit "/"
    fill_in "q", :with => text
    click_button "Search"
  end
 
  def ensure_results_contain(expected_text)
    page.should have_content(expected_text)
  end
end
 
google = Google.new
google.search_for("Matt Wynne")
google.ensure_results_contain("Tea")

To make this work you’ll need to install the capybara and rspec Ruby gems:

gem install capybara rspec

Agile / Lean Software Development
Ruby Programming

Comments (2)

Permalink

Installing Ruby Gems with Native Extensions on Windows

If you’re stuck trying to run Ruby on Windows, one barrier you might have encountered is in trying to install a gem like ruby-debug or rdiscount. You’ll have seen an error like this:

%gem install ruby-debug
Building native extensions.  This could take a while...
ERROR:  Error installing ruby-debug:
        ERROR: Failed to build gem native extension.
 
C:/Ruby187/bin/ruby.exe extconf.rb
creating Makefile
 
make
'make' is not recognized as an internal or external command, operable program or batch file.
 
 
Gem files will remain installed in C:/Ruby187/lib/ruby/gems/1.8/gems/linecache-0.43 for inspection.
Results logged to C:/Ruby187/lib/ruby/gems/1.8/gems/linecache-0.43/ext/gem_make.out

That’s no fun.

The good news is, the lovely guys at Ruby Installer have put together a fix, called the DevKit. This installs the low-level bits and pieces needed to build those pesky native extensions on your Windows machine. There are a couple of manual steps which I didn’t find especially clear, so I’m documenting them here.

  • Download the DevKit self-extracting archive here
  • Run the archive, and when prompted, choose to extract it to C:\DevKit
  • When the archive has finished unpacking, open a command prompt in C:\DevKit and run ruby dk.rb init ruby dk.rb install
  • That’s it. You can test it using: gem install ruby-debug

Hooray!

Ruby Programming

Comments (5)

Permalink

Fix RubyMine 2.02 Cucumber Integration

If you’re using the latest version of RubyMine (2.0.2) with the latest version of Cucumber (actually anything above 0.7), you’ll probably see this ugly warning when you try to run your cukes from within the IDE:

screen-shot-of-rubymine-error

The bug has been logged, and there’s a published workaround, but I wanted something a bit easier to use.

Try this instead. Close RubyMine, open a terminal, and run this command:

curl http://gist.github.com/raw/550046/240dd98b8b0ed1efa817f26ff2697940ddd0f53d/rubymine-2.02-cucumber.patch | patch -p0

or even

curl -L http://bit.ly/bPNmYV | patch -p0

It won’t work with Cucumbers older than 0.7, but why would you want to use them?

Update: If you like life on the bleeding edge, you can also try the EAP release (latest development build) of the forthcoming RubyMine 2.5, which contains this fix.

Ruby Programming

Comments (0)

Permalink

Installing mysql gem on Mac OSX Snow Leopard

This old chore doesn’t seem to have become any easier lately. Here’s how to do it: http://blog.simb.net/2009/10/24/gem-mysql-with-mysql-5-1-on-snow-leopard/

Ruby Programming

Comments (0)

Permalink

MegaMutex: A Distributed Mutex for Ruby

Sometimes I need to do this:

unless enough_widgets?
  make_more_widgets
end

Which is all well and good, until I start letting two or more of these codes run in parallel. If you’ve never thought about this before, what can happen is something nasty called a race condition, where two or more processes (or threads) simultaneously check #enough_widgets?, and simultaneously both decide that they need to go and #make_more_widgets. With multiple processes now making more widgets, we end up with too many.

The solution is to lock this critical section of code so that only one process could ever run it at once – everyone else has to queue up and wait their turn. That way each check for #enough_widgets? will return an answer that’s accurate. In a single process with threads, this is achieved using the Mutex class, but when you run multiple processes in parallel, across multiple machines, you need something more. You need MegaMutex.

How

Suppose you have a WidgetMaker:

class WidgetMaker
  include MegaMutex
 
  def ensure_just_enough_things  
    with_distributed_mutex("WidgetMaker Mutex ID") do
      unless enough_widgets?
        make_more_widgets
      end
    end
  end
end

Now, thanks to the magic of MegaMutex, you can be sure that all processes trying to run this code will wait their turn, so each one will have the chance to make exactly the right number of widgets without anyone else poking their nose in.

Configuration

MegaMutex uses memcache-client to store the mutex, so your infrastructure must be set up to use memcache servers.

By default, MegaMutex will attempt to connect to a memcache on the local machine, but you can configure any number of servers like so:

MegaMutex.configure do |config|
  config.memcache_servers = ['mc1', 'mc2']
end

Installation

sudo gem install mega_mutex

Hacking

http://github.com/songkick/mega_mutex

Ruby Programming

Comments (2)

Permalink

PartialDebugger Plug-in for Rails

Ever look at the HTML output from an old project and wonder which the hell partial rendered which the heck bit of the HTML?

Wonder no more.

./script/plugin install git://github.com/mattwynne/partial_debugger.git

Then add this to your config/environments/development.rb

PartialDebugger.enable

…because you probably don’t want this running in production.

Ruby Programming

Comments (0)

Permalink

Rails Tip: Use Polymorphism to Extend your Controllers at Runtime

Metaprogramming in Ruby comes in for quite a bit of stick at times, the accusation being that code which modifies itself at runtime can be hard to understand. As Martin Fowler recently described, there’s a sweet spot where you use just enough to get some of the incredible benefits that Ruby offers, without leaving behind a minefield for future developers who’ll have to maintain your code.

One of my favourite techniques uses the Object#extend method, which allows you to mix in the methods from a module to a specific instance of a class at run-time. In my quest to eliminate as much conditional logic as possible from my code, I’ve seen a common pattern emerge a few times. Here’s an example from a refactoring session I paired on with my colleague craig.

We start with a Rails controller which handles user authentication. Over the passing iterations, it has grown to support not only bog-standard logins from users of the main web application, but a form that’s displayed on a 3rd-party partner site, as well as during the installation of a rich-client GUI app. All these clients need slightly different behaviour – different templates or layout to be rendered, and different destination pages to redirect to when the login has succeded.

Sadly the hackers passing through this controller have not been great boy scouts, and the code has started to get pretty unpleasant. This code is simplified for clarity:

class SessionsController < ApplicationController
 
  def new
    if params[:installer]
      render :layout => 'installer_signup', :action => 'installer_signup')
    else
      render :layout => 'modal'
    end
  end
 
  def create
    if params[:username].blank?
      flash[:error] = "Please enter a username"
      return render_new_action
    end
 
    unless user = User.authenticate(params[:username], params[:password])
      flash[:error] = "Sorry, that username was not recognised"
      return render_new_action
    end
 
    set_logged_in_user(user)
 
    if params[:installer]
      @username = user.username
      return render(:template => 'installer_done', :layout => 'installer_signup' )
    elsif params[:third_party]
      return render(:template => "third_party/#{params[:third_party]}")
    else
      return redirect_to(success_url)
    end
  end
end

Notice how the conditional logic has a similar structure in both actions. Our refactoring starts by introducing a before_filter which works out the necessary extension:

class SessionsController < ApplicationController
 
  before_filter :extend_for_client
 
  ....
 
  private
 
  def extend_for_client
    self.extend(client_exension_module) if client_exension_module
  end
 
  def client_extension_module
    return InstallerClient if params[:installer]
    return ThirdPartyClient if params[:third_party]
  end
 
  module InstallerClient
  end
 
  module ThirdPartyClient
  end
end

Notice that we don’t bother extending the controller for the ‘else’ case of the conditional statements – we’ll leave that behaviour in the base controller, only overriding it where necessary.

Now let’s extract the client-specific code out of the create action into a method that we’ll override in the modules:

class SessionsController < ApplicationController
 
  ...
 
  def create
    if params[:username].blank?
      flash[:error] = "Please enter a username"
      return render_new_action 
    end
 
    unless user = User.authenticate(params[:username], params[:password])
      flash[:error] = "Sorry, that username was not recognised"
      return render_new_action 
    end
 
    set_logged_in_user(user)
 
    handle_successful_login
  end
 
  private 
 
  def handle_successful_login
    if params[:installer]
      @username = user.username
      return render(:template => 'installer_done', :layout => 'installer_signup' )
    elsif params[:third_party]
      return render(:template => "third_party/#{params[:third_party]}")
    else
      return redirect_to(success_url)
    end
  end
 
  ...

Finally, we can the client-specific code into the appropriate module, leaving the default behaviour in the controller:

class SessionsController < ApplicationController
 
  before_filter :extend_for_client
 
  def new
    render :layout => 'modal'
  end
 
  def create
    if params[:username].blank?
      flash[:error] = "Please enter a username"
      return render_new_action 
    end
 
    unless user = User.authenticate(params[:username], params[:password])
      flash[:error] = "Sorry, that username was not recognised"
      return render_new_action 
    end
 
    set_logged_in_user(user)
 
    handle_successful_login
  end
 
  private 
 
  def handle_successful_login
    return redirect_to(success_url)
  end
 
  private
 
  def extend_for_client
    self.extend(client_exension_module) if client_exension_module
  end
 
  def client_extension_module
    return InstallerClient if params[:installer]
    return ThirdPartyClient if params[:third_party]
  end
 
  module InstallerClient
    def new
      render :layout => 'installer_signup', :action => 'installer_signup')
    end
 
    private 
 
    def handle_successful_login
      @username = user.username
      return render(:template => 'installer_done', :layout => 'installer_signup' )
    end
  end
 
  module ThirdPartyClient
    def handle_successful_login
      return render(:template => "third_party/#{params[:third_party]}")
    end
  end
end

Polymorphism is one of the power-features of an object-oriented language, and Ruby’s ability to flex this muscle at run-time opens up some really elegant options.

Ruby Programming

Comments (1)

Permalink

Goodbye CruiseControl.rb, Hello Hudson

Imagine you have a friend who writes a blog. Maybe you actually do. Let’s call him ‘Chump’. One day you’re chatting, and the conversation turns to technology. It turns out that Chump is using Dreamweaver to write his blog entries, and manually uploading them to his site via FTP. You’re appalled.

How do you update the RSS feed?

you enquire, trying to conceal the horror in your voice.

Oh, I just edit the Atom file manually, it’s not that hard.

says Chump.

Maybe nobody ever told Chump about wordpress.

At work, we just switched our build server from CruiseControl.rb to Hudson, and we won’t be looking back.

Ruby people, for some reason, seem distinctly inclined to use build servers made out of Ruby too. That’s nice and everything, but these things are childsplay in comparison to the maturity, usability, and feature-set of hudson.

Here’s why I recommend you switch to hudson for your Ruby / Git projects:

  • open source
  • piss easy to set up, even if you have no idea what java even is
  • solid git support
  • works with CCMenu (or your favourite CruiseControl monitoring desktop widget)
  • kill builds from the GUI
  • in fact, manage everything from the GUI
  • distributed architecture, allowing you to delegate builds to multiple machines
  • huge, active plug-in support
  • you have better things to do with your time than faff around hacking on your build server

The problem is, it doesn’t have a smug website with fancy branding, so you probably overlooked it the first time. Go back and take another look.

Ruby Programming

Comments (26)

Permalink