Latest News

...

2009/05/21

Obama speaks up about Guantanamo
More...

2009/05/03

Independent film inspired by J.R.R. Tolkien's Lord of the Rings
More...

2009/04/16

A terrorist's garbage bin
More...

2009/04/09

Open classes and overloading methods in Ruby
More...

2009/04/05

Openmoko suspends development of the GTA03 smartphone
More...

2009/02/08

Video demonstration of interactive computer vision
More...

2009/02/04

Presentation about computer vision and the Ruby programming language
More...

2009/01/31

Ruby 1.9 brings native threads, fibers, and Unicode support
More...

...

|< << >> >|

Avoiding alias_method_chain in Ruby (2009/04/09)

I currently use Ruby a lot but since I am not into developing web applications, I am not knowledgeable about Ruby on Rails. So when I watched Yehuda’s presentation about refactoring Rails I watched it not so much because of Rails but because of refactoring Ruby software.

Yehuda Katz - The Great Rails Refactor

Yehuda talks about introducing modules to be able to use super instead of alias_method_chain. I tried it out on an example and it seems to be a really useful thing to know.

Using alias_method_chain

This approach uses the popular definition of alias_method_chain

1 class Module
2   def alias_method_chain( target, feature )
3     alias_method "#{target}_without_#{feature}", target
4     alias_method target, "#{target}_with_#{feature}"
5   end
6 end

As an example we have a class Test with a method x

 7 class Test
 8   def x
 9     'x'
10   end
11 end

Using alias_method_chain the method x can be extended without having to introduce a new inheriting class

12 class Test
13   def x_with_two
14     "#{x_without_two}2"
15   end
16   alias_method_chain :x, :two
17 end

The method now exhibits the new behaviour

puts Test.new.x
# "x2"

Using modules

However the method x can be declared in a module which is included by Test

 1 module X
 2   def x
 3     "x"
 4   end
 5   module_function :x
 6 end
 7 class Test
 8   include X
 9   public :x
10 end

Overloading the method now can be done by including another module which has a new definition of x. The new method x can invoke the previous one by calling super

11 module X2
12   def x
13     "#{super}2"
14   end
15   module_function :x
16 end
17 class Test
18   include X2
19 end

The method now exhibits the new behaviour

puts Test.new.x
# "x2"

The issue with this approach is that overloading of the method needs to be anticipated. However at the same time the code indicates it more clearly that the first definition of x is not necessarily the final one in objects of type Test. Moreover this approach works without public definitions of methods you are not supposed to call (e.g. x_without_two).

Update: If you like to see another talk from MountainWest RubyConf 2009, you should check out Jim Weirich’s talk on The Building Blocks of Modularity.

See also:

Blog comments powered by Disqus