Yehuda Katz is a member of the Ember.js, Ruby on Rails and jQuery Core Teams; he spends his daytime hours at the startup he founded, Tilde Inc.. Yehuda is co-author of best-selling jQuery in Action and Rails 3 in Action. He spends most of his time hacking on open source—his main projects, along with others, like Thor, Handlebars and Janus—or traveling the world doing evangelism work. He can be found on Twitter as @wycats.
alias_method_chain in models
March 6th, 2009
As people know, there’s been a fair bit of back-and-forth between me, the apparent foe of alias_method_chain, and folks who feel that alias_method_chain is a perfectly reasonable API that people should not blindly hate.
There are basically two use-cases for alias_method_chain:
- Organizing internal code
- Modifying existing code
Using alias_method_chain to organize internal code is an interesting discussion that I will hopefully continue to have into the future. Today, I want to address uses of alias_method_chain to override methods in ActionController::Base or ActiveRecord::Base. People who do this are blindly using the technique that has been most evangelized as the solution to all their problems when Ruby comes with a perfectly good solution.
Consider this post from vaporbase, which I am decidedly not picking on. It represents a common idiom that people have been trying to use in Rails. First, the usage in a model:
class Foo < ActiveRecord::Base include FooBar end |
Second, the code implementation:
module FooBar module ClassMethods def find_with_bar( *args ) find_without_bar( *args ) #...or whatever end end def self.included(base) base.class_eval do extend ClassMethods class << self alias_method_chain :find, :bar end end end end |
This is exactly equivalent to:
module FooBar def self.included(base) base.extend(ClassMethods) end module ClassMethods def find(*args) super #...or whatever end end end |
That’s right… if you’re looking to modify subclasses of ActiveRecord::Base or ActionController::Base, keep in mind that you’re (gasp) in an OO language with inheritance and super.
If you want to modify all of the models in your application, create your own custom ActiveRecord::Base subclass, and inherit from that throughout your application. That’s what inheritance is there for!
Another example
Another example, by a very, very smart person, goes even further overboard.
First, he started with:
class Post < ActiveRecord::Base class << self def find_with_tags(*args) options = extract_options_from_args!(args) if tag = options.delete(:tags) options[:select] ||= 'posts.*' options[:joins] ||= '' options[:joins] << <<-END INNER JOIN posts_tags AS inner_posts_tags ON posts.id = inner_posts_tags.post_id INNER JOIN tags AS inner_tags ON inner_tags.id = inner_posts_tags.tag_id END add_to_conditions(options, tags.map { 'inner_tags.name = ?' }.join(' OR '), *tags) end find_without_tags(*(args + [options])) end alias_method_chain :find, :tags def find_with_query(*args) options = extract_options_from_args!(args) if query = options.delete(:query) if query.empty? add_to_conditions(options, 'false') else term = "%#{query}%" add_to_conditions(options, "posts.content LIKE ? OR posts.title LIKE ?", term, term) end end find_without_query(*(args + [options])) end alias_method_chain :find, :query protected def add_to_conditions(options, condition, *args) condition = args.empty? ? condition : [condition, *args] if options[:conditions].nil? options[:conditions] = condition else options[:conditions] = sanitize_sql(options[:conditions]) + " AND (#{sanitize_sql(condition)})" end end end end |
Noticing it wasn’t very DRY, he resorted to metaprogramming:
class Post < ActiveRecord::Base class << self def handle_find_option(name, &block) eigenclass = class << self; self; end eigenclass.send :define_method, "find_with_#{name}_handled" do |*args| options = extract_options_from_args!(args) if option = options.delete(name) block[options, option] end send("find_without_#{name}_handled", *(args + [options])) end eigenclass.send :alias_method_chain, :find, "#{name}_handled" end end end class Post < ActiveRecord::Base handle_find_option(:tags) do |options, tags| options[:select] ||= 'posts.*' options[:joins] ||= '' options[:joins] << <<-END INNER JOIN posts_tags AS inner_posts_tags ON posts.id = inner_posts_tags.post_id INNER JOIN tags AS inner_tags ON inner_tags.id = inner_posts_tags.tag_id END add_to_conditions(options, tags.map { 'inner_tags.name = ?' }.join(' OR '), *tags) end handle_find_option(:query) do |options, query| if query.empty? add_to_conditions(options, 'false') else term = "%#{query}%" add_to_conditions(options, "posts.content LIKE ? OR posts.title LIKE ?", term, term) end end end |
An alternative, using super:
class Post < ActiveRecord::Base class << self def find(*args) options = args.last.is_a?(Hash) ? args.last : {} add_tag_conditions(options) add_query_conditions(options) super end private def add_tag_conditions(options) if tag = options.delete(:tags) options[:select] ||= 'posts.*' options[:joins] ||= '' options[:joins] << <<-END INNER JOIN posts_tags AS inner_posts_tags ON posts.id = inner_posts_tags.post_id INNER JOIN tags AS inner_tags ON inner_tags.id = inner_posts_tags.tag_id END add_to_conditions(options, tags.map { 'inner_tags.name = ?' }.join(' OR '), *tags) end end def add_query_conditions(options) if query = options.delete(:query) if query.empty? add_to_conditions(options, 'false') else term = "%#{query}%" add_to_conditions(options, "posts.content LIKE ? OR posts.title LIKE ?", term, term) end end end def add_to_conditions(options, condition, *args) condition = args.empty? ? condition : [condition, *args] if options[:conditions].nil? options[:conditions] = condition else options[:conditions] = sanitize_sql(options[:conditions]) + " AND (#{sanitize_sql(condition)})" end end end end |
We just override find, have it modify the options as appropriate, and call super. This same technique works fine for your own applications’ ActionController modifications, and in any case where the framework API involves subclassing. Folks: this is what subclassing is FOR!

Daniel, Posted March 6, 2009, 8:49 pm
I think you should mention that this requires your classes to be structured a certain way and you need control over the class you are intending to change.
ForExample assume you have:
class Foo < ActiveRecord::Base
def self.ordered(*args)
# some stuff here
end
end
and you want to change the arguments passed to ordered. If you create a module as in your first example which should wrap around ordered method this won’t work. You would need the original method ordered to be included into Foo to be defined already in a module so you get an ancestor chain of: Foo, ModuleWithNewOrderedMethod, ModuleWithOriginalOrderedMethod
wycats, Posted March 6, 2009, 8:56 pm
@daniel: that is the usual argument against my generic alias_method_chain position. This is much more limited to things that are defined on AR::Base or AC::Base and where you want to make app-specific changes.
In that case, no caveats are necessary, and that was my point.
Hampton Catlin, Posted March 6, 2009, 11:20 pm
*HEADDESK*
Holy crap. So obvious. Why on earth did I get into the habit of using alias? I should have just used super.
God. I. Am. An. Idiot.
Jan, Posted March 7, 2009, 11:56 am
I agree. super is definitely an under used keyword in ruby, which is an object-oriented language.
Bob Aman, Posted March 7, 2009, 10:22 pm
Here, here. Couldn’t have said it better myself.
Sergio, Posted March 9, 2009, 2:20 pm
The voice of reason… Thanks!
hukl, Posted March 9, 2009, 5:58 pm
Hmm but you’d still have to define a “find_without_options” method to access the original find? Could also be that I’m missing something here. Not sure. Can someone clue me in?
wycats, Posted March 9, 2009, 8:02 pm
Nah. You’d just use super to access the original.
hukl, Posted March 10, 2009, 2:28 am
Could you provide an example. Sorry I don’t understand how you would access the original find.
Like you define a new find in the FooBar module and inlclude it into the Foo class. Now Foo inherited find from ActiveRecord, but with the module inclusion, its got its own find now which first calls super and does some custom stuff. So far so good. Now when I want to call the original Foo.find method, the one it has inherited, I would call Foo.super.find ?
Sorry again for my cluelessness ;) I like your examples but I want to fully understand them ;)
hukl, Posted March 10, 2009, 2:51 am
So I played a bit with that concept, but its in the morning and I still can’t figure it out. This is what I have:
http://pastie.textmate.org/private/dgmvvqvygqwlqoprkrtftg
How could I call the orginal .say_hello here which only puts “say hello to the real world” ?
Thanks in advance!
hukl, Posted March 10, 2009, 3:00 am
The only way I found was to call Foo.superclass.say_hello or Foo.superclass.find to stick with your example which would be totally okay i guess.
def original_find
self.superclass.find
end
Is that the way then ?
wycats, Posted March 10, 2009, 4:03 am
You wouldn’t! The idea here is to modify the “save” functionality to modify it with some changes. If you *really* need access to the old functionality alone, you could do what you suggested (
def original_find(*args, &blk) self.superclass.find(*args, &blk))But honestly, if you wanted the original around, you should probably alias it off to the side for continued use, and then redefine the original method and use super.
hukl, Posted March 10, 2009, 9:36 am
Alright thank you!
wycats, Posted March 10, 2009, 10:16 am
Heh… I give bad replies when I’m half-asleep. Probably a better approach:
def find(*args) options = args.last.is_a?(Hash) ? args.last : {} unless options.delete(:skip_my_new_feature) # perform new feature end super endThis effectively provides a flag to turn off the new feature through the existing API. This sort of API is already in use by Rails (via a_m_c) in AR::Base#save, and it works better than trying to access an incidental byproduct of a_m_c.
Asfand Yar Qazi, Posted July 31, 2009, 12:38 am
I was GOING to use alias_method in a custom form builder that I was writing, so that the form could either use (for example) the text_field method if it wanted the customizations the custom form builder introduced, or resort to (for example) original_text_field if it did not (the aliased-away old method).
But then I found something. The excellent Ruby Facets library introduces a method called ‘Kernel#as’ (description: “Returns a As-functor that allows one to call any ancestor‘s method directly of the given object.”)
So I now have a method in the form builder called ‘original’, which is simply:
def original; return self.as(ancestor); end
So the form can choose to have the customizations provided by my form builder if it wants, by simply using text_field, or it can do this if I have a unique requirement that I don’t want to hack into the form builder (because it’s only going to be used once):
Another reason to use alias_method instead of super gone!
Note on usage: ‘form.original.send(:text_field, …)’ doesn’t work. Kernel#as can’t be used like this, you have to use Kernel#send_as
Nathan de Vries, Posted August 8, 2009, 2:08 am
I have a feeling that many people learn these techniques by looking at gems and plugins, and end up using them in their own applications where inheritance would be more appropriate.
But in the case of gems and plugins, alias_method_chain is exactly what you would want to use to sprinkle additional functionality on top of standard Rails methods without forcing users to adopt a different API. A good example of this is will_paginate, which allows users to call paginate() on standard AR::Base collections without modifying their models to inherit from something like WillPaginate::PaginatedRecord.
Michael Johnston, Posted September 3, 2009, 4:26 pm
@Nathan: which, to be honest, totally sucks from a maintainability standpoint in larger projects.
I would rather the model class DID tell you which bits of plugins it was using which change the behaviour of the standard api.
Rasheed Abdul-Aziz, Posted September 21, 2009, 10:13 pm
Isn’t it generally held that calling super is an anti-pattern? I’ve always found it to be a fairly brittle approach to anything I do, and replace it with IOC/DI anywhere I can, especially when coding in a statically typed language. In Rails and Ruby, I thought the method aliasing approach was a far healthier approach so long as everyone is cautious about what the extend. Aliasing gives us multiple-inheritance, which isn’t hideous, so long as you’re clearly not out to hang yourself. Rubyists idiomatically avoid hanging themselves, and so welcome multiple inheritance in this way.
Or have I missed something obvious.
Lailson Bandeira, Posted April 13, 2010, 1:01 pm
But how can we “override” attributes readers and writers in ActiveRecord without alias_method_chain? There inheritance really cannot help and using attributes directly don’t work for some conversions and dirty relation states.
Does it was removed from Rails 3?
Marnen Laibow-Koser, Posted August 17, 2010, 12:05 pm
Rasheed: Why would calling super be an antipattern? I’ve never heard this said of any language. It seems to me that calling super is a very *good* thing to do in most cases. What problems have you had with it? It’s a much better solution than circumventing the object model with alias_method_chain, I think.
Gabe da Silveira, Posted September 14, 2010, 1:27 am
Agree with Marnen here. I don’t see how super can be more brittle than alias_method_chain. If you *do* call foo_without_bar, you are still depending on the implementation of the original (possibly moreso since you don’t get the equivalent automagical argumentless super). If you *don’t* call :foo_without_bar then you wouldn’t need to call super anyway.
I think the crux of the issue here is do you have a place in the method lookup hierarchy to insert your new method. In the case of ActiveRecord models you always do because you are creating an explicit subclass. In fact, thanks to the metaclass, you can go far with this.
korinthe, Posted October 5, 2010, 1:27 pm
I found your post via chadfowler.com while trying to figure out a solution for overriding the attribute readers/writers in multiple (sibling) subclasses of AR::Base. Naturally I first tried mixing in a module HasFoo, with foo() defined in it, and naturally it didn’t work.
Lailson is wondering about this too; could you perhaps say a bit more about how you’d deal with that example?
Ernie Miller, Posted February 3, 2011, 12:32 pm
This post has some fantastic discussion in the comments about the exceptions to the rule, but just yesterday I ran into a case where someone didn’t understand the means by which super can replace alias_method_chain in many/most cases. As such, I wrote up a quick post that hopefully explains a situation in which it becomes necessary to resort to alias_method_chain in more detail.
Anyway, the post can be found over at http://metautonomo.us/2011/02/03/when-to-use-alias_method_chain/, and it basically just expands on the situation that Daniel outlined in his very first comment some time ago, for those who didn’t read it or had trouble following.
Seemed like, since discussion is still sputtering along on this (nearly two year old!) post, it might be worth linking from here. Thanks for reading!
Oleh Novosad, Posted November 15, 2012, 10:34 am
Extending rails functionality without alias_method_chain
module ActiveRecordUuid
module AssociationMethods
def has_many(name, options = {}, &extension)
options = uuid_assoc_options(:has_many, name, options)
super
end
……..
end
end
ActiveRecord::Base.send(:extend, ActiveRecordUuid::AssociationMethods)