I've been meaning to do this for a while because I keep coming across alias_method and alias_method_chain in Rails code. I understood what was going on, but felt that I never grokked it. So, I finally mapped out what happens, drew some pictures, and, voila! Enlightenment!
Since I firmly believe that the best way to learn something is to teach it, I thought I would document what I learned in the hopes that it will be beneficial to someone else and firmly cement my understanding. So without further ado:
It is important to keep in mind that a method name is essentially a constant symbol and points to a block of code. "alias_method" is a Ruby class Module method with the signature:
alias_method(new_name, old_name)
And, "alias_method_chain" looks like this:
alias_method_chain :method_name, :feature
That's the easy part.
For the purpose of this example, I'm examining the behavior of:
alias_method_chain :render, :feature
The
alias_method method makes a copy of the method block and assigns the new_name constant to point to the copy of the method block. So, it looks something like this:
Here's the method
render and its method block:
After we call
alias_method :render_without_feature, :render we have the following:
At this point, if we wanted to, we could redefine the
render method, which would replace the original {render} block with new functionality. And, as it is often explained, the original functionality is still available at the
render_without_feature method.
However, as it is often explained, what is desired in Rails library code is to redefine an existing method while saving the original functionality under a new name. Therefore, what we see in Rails code was often:
alias_method :render_without_feature, :render
alias_method :render, :render_with_feature
We already looked at the first line. Let's look at the second line.
The second line is assigning the constant "render" to a copy of the "render_with_feature" functionality. It looks like this:
Now,
render will call the code block with the new feature and
render_without_feature will call the original render block.
This is the key to the entire Rails helper,
alias_method_chain, which takes the name of the original method and the name of the feature and does this mapping for us.
Therefore, the two
alias_method calls above can be replaced with the following:
alias_method_chain :render, :feature
You, the fine engineer, will define a method
render_with_feature and the
render symbol will point to it. And, after the
alias_method_chain call, you will have a new
render_without_feature method created for you.
I find all of this rather elegant and hope this has been helpful