Ruby Fleebie

Rediscovering the joy of programming

How to hook to an Array instance in a Ruby module

On some project we needed to create a module containing an Array attribute. We wanted to hook onto some of the methods of this particular Array instance to call our own code. Here is how we did it:

module TheModule
  attr_reader :items
  def initialize(*args)
    @items = []

    def @items.<<(item)
      super
      "You added the item #{item} with <<!"
    end

    def @items.push(item)
      super
      "You added the item #{item} with push!"
    end
    super
  end
end

class TheClass
  include TheModule
end

And now the output:

x = TheClass.new
x.items   # => []
x.items << 'blue' # => You added the item 'blue' with <<!
x.items.push 'orange' # => You added the item 'orange' with push!
x.items # => ["blue", "orange"]

Every Little Things Capistrano Does Is Magic

During all these years, Capistrano has been for me a magical gnome that I invoke by saying “cap deploy, my magical friend!” and then I close my eyes, sing a happy song in my head and when the gnome has finished his magic, I hit F5 to see if all went well. And of course, if it didn’t, I blame the damn elf.

I am proud of this introduction. I will take a sip of coffee and read it again, hold on. Yes this intro was good, I think I should write about magical little beings more often.

If you are like me, you never paid much attention to capistrano and the way it works. At the exception of the famous “cap deploy” command, you never really wanted to get involved in the process. For this reason you have copied and pasted the same old deployment recipe in all of your projects over the years, only changing some parameters like the application name and the emplacement of the git repository.

The fact that capistrano is doing magical things doesn’t really help in this regard. My goal in this post is to explain some of the not so obvious parts of capistrano. With minimal efforts we can have a better idea of what capistrano does and feel more in control when deploying an application.

Capistrano is magic

Like many things in the ruby world, there is a fair bit of magic involved in capistrano. For example, when you type “cap deploy”, there is a bunch of things that happen, but what things exactly? What tasks are being called? This is not obvious. First of all, “deploy” is not a task written in your own recipe file, it is a namespace located in the capistrano gem. Take a look:

namespace :deploy do
  desc <<-DESC
    Deploys your project. This calls both `update' and `restart'. Note that \
    this will generally only work for applications that have already been deployed \
    once. For a "cold" deploy, you'll want to take a look at the `deploy:cold' \
    task, which handles the cold start specifically.
  DESC
  task :default do
    update
    restart
  end
#...

As you can see, the :default task is invoked when you type “cap deploy”, which in turns will call “update” and “restart”.

This is why you never got to see a call to the :restart task in your own recipe file. I know that during all these years there was a secret part of your brain that was¸wondering about this stuff, while the not-so-secret part really didn’t care.

Capistrano and Bundler

  require 'bundler/capistrano'

This line adds some bundler magical stuff to your recipe. It will install your bundle (with the –deployment flag) when deploying, meaning that all your gems will be vendored to yourapp/shared/bundle.

Capistrano and the Asset Pipeline

load "deploy/assets"

This line adds some magical stuff for compatibility with the Rails 3.1+ asset pipeline. More precisely, it will precompile your assets. This is an almost essential part when you use the asset pipeline in production. The other solution is to precompile locally and push the assets to your repository, not a good idea in my opinion. The sad part is that precompiling assets can slow down your deployment quite severly. If you use GIT, you might like this smart solution from Ben Curtis to skip assets precompilation.

Capistrano and RVM

$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
require "rvm/capistrano"
set :rvm_ruby_string, 'ruby-1.9.2-head@rails3.2'
set :rvm_type, :user

This tells capistrano to switch to a specific ruby version + gemset when connected to the server. The gemset (i.e. @rails3.2) is the tricky part because it makes you think that, when capistrano will invoke bundle install, your gems will be installed in .rvm/gems/ruby-1.9.2-head@rails3.2/gems. This is not the case. Remember that we have just told bundler to install the gems in yourapp/shared/bundle/.

So why do we bother with the gemset anyway?

One reason is that the bundler gem itself will be invoked by capistrano on your server in the gemset specified in the rvm_ruby_string variable. It can be useful to specify a gemset if you want to use a specific version of bundler.

That's all folks!

Should ruby go the haml route and uses significant whitespaces?

Before I start, let me get something straight: I’m not saying it would be a good or bad idea… I’m just asking the question.

I must say that my first experience with a significant whitespace language was a disaster. The first time I had to use Python was on a server via ssh. I was in a hurry and wanted to monkey patch some buggy script I had installed. So without thinking too much I opened the script with a text editor called nano. The problem is that a TAB in nano produces between 173 and 177 white spaces. Realizing this I decided to refrain from indenting one line or two because it was too ugly and unreadable. Then python told me that I could not do this… and at the time I remember thinking it was unacceptable that a script start to malfunction just because of a few missing whitespaces. Anyway, I spent some long minutes trying to fix a few indentation issues (in nano! I still didn’t realize it was the source of the problem) and it was very tedious. Had I try debugging the python script on my local computer with gedit for example, things would surely have turned out differently.

Then Haml came… and I stayed away

This unpleasant experience I had with Python had a rather negative side effect: It made me completely ignore Haml for a long time, which is sad because it is such a great alternative to erb.

But now I use Haml, and I really like it. Not having to “close my tags” is more satisfying than I thought it would be. I always delight when I realize I was about to write a “- end” tag to close a “- @items.each” loop or something like that. I don’t have to! Less typing, less noise, cleaner, prettier, I love this! Wouldn’t be nice if we could do away with the “end” keyword in ruby as well?

Just to give us an idea, here is how an actual class from the Haml gem would look like if it was written in Significant Whitespace ruby:

    class ParseNode < Struct.new(:type, :line, :value, :parent, :children)
      def initialize(*args)
        super
        self.children ||= []

      def inspect
        text = "(#{type} #{value.inspect}"
        children.each {|c| text << "\n" << c.inspect.gsub(/^/, "  ")}
        text + ")"

Great, it sill looks like ruby. We just removed some noise to make it even more readable.

Let’s convert a longer method, still from the Haml gem, to see how it would look like:

    def parse_new_attributes(line)
      line = line.dup
      scanner = StringScanner.new(line)
      last_line = @index
      attributes = {}

      scanner.scan(/\(\s*/)
      loop do
        name, value = parse_new_attribute(scanner)
        break if name.nil?

        if name == false
          text = (Haml::Shared.balance(line, ?(, ?)) || [line]).first
          raise Haml::SyntaxError.new("Invalid attribute list: #{text.inspect}.", last_line - 1)

        attributes[name] = value
        scanner.scan(/\s*/)

        if scanner.eos?
          line << " " << @next_line.text
          last_line += 1
          next_line
          scanner.scan(/\s*/)

      static_attributes = {}
      dynamic_attributes = "{"
      attributes.each do |name, (type, val)|
        if type == :static
          static_attributes[name] = val
        else
          dynamic_attributes << inspect_obj(name) << " => " << val << ","

      dynamic_attributes << "}"
      dynamic_attributes = nil if dynamic_attributes == "{}"

      return [static_attributes, dynamic_attributes], scanner.rest, last_line

Well, not bad at all… the only problem is that the loop is quite long and I had to double-check to know if the “static_attributes” statement was part of the loop or right after. This kind of double checking could get on my nerves fast.

I’m still undecided. I dislike end tags but they can clear things up sometimes. Anyway, I guess we probably never see this implemented in ruby. What’s your thoughts on significant whitespace languages?