af83

Ruby 2.0 : Module#prepend

With a release date set to the 24th February 2013, the next major version of Ruby is around the corner. So what Ruby 2.0 will have to offer for its twentieth candle?

Like every new version of a language, this iteration will bring some performance improvements (yay, copy on write), and some new features.

Let's talk about a new method that will add a major change to the Ruby's model object, Module#prepend.

If you already clicked on that link, you can see that the documentation is not really up to date…

Ruby methods lookup

Consider this example :

module FooBar
  def hello
    puts 2
    super
  end
end

class Foo
  def hello
    puts 'hello'
  end
end

class Bar < Foo
  include FooBar
  def hello
    puts 1
    super
  end
end

Bar.new.hello

Ouputs the following:

1
2
"hello"

The Bar class inherits from Foo, and includes the module FooBar. When the method hello is called on a instance of Bar, the following is happening: First, it outputs "1", then it calls the same method with super, but one step above in the hierarchy, which is the module FooBar, prints 2, and calls super.

So, it looks in its own class, then in included modules, and then in class hierarchy.

Seems quite legit, but sometimes, you want a method from a module to take the precedence on a method from the class. There are some solutions to accomplish this task, like alias_method_chain, but it's more a hack than anything - and not really safe.

Module#prepend

Module#prepend does exactly that. Now let's see how it works with a new example (Ruby 2.0 is needed for this one):

module FooBar
  def hello
    puts 2
    super
  end
end

class Foo
  def hello
    puts 'hello'
  end
end

class Bar < Foo
  prepend FooBar

  def hello
    puts 1
    super
  end
end

Bar.new.hello

This code example looks very much like the previous one, except that the module is prepended instead of included. Meaning that methods from these modules will have the precedence over the class.

But with a different output:

2
1
"hello"

Way safer and nicer that alias_method_chain or some monkey patching.

Thanks to Module#prepend, a module for memorization or a cache over some orm could be easily done. I'm pretty sure that prepend will solve some problems in a nice way; and looking forward to use it in a few months.

Coming next in this series: Module#refine.

blog comments powered by Disqus