Ruby / How to alias and override a class method
From WhyNotWiki
My hovercraft is full of eels: Alias a Static Method in Ruby (http://www.redhillconsulting.com.au/blogs/simon/archives/000326.html).
In Ruby, the way to safely mix-in methods (rather than use subclassing) is to use some method chaining. For this we use alias_method. So, for example, if we wanted to override to_s to always place quotes around the value (nopt very useful but it will suffice for now) we could write a module like this:
module QuoteToS def self.included(base) base.class_eval do alias_method :to_s_without_quotes, :to_s unless method_defined?(:to_s_without_quotes) alias_method :to_s, :to_s_with_quotes end enddef to_s_with_quotes "'#{to_s_without_quotes}'" end endThis essentially says that when the module is included (ie mixed-in) to a class then: add a method named to_s_with_quotes; create an alias of the existing to_s named to_s_without_quotes; make an alias of the new to_s_with_quotes named to_s; and finally, whenever to_s. is executed, call the old to_s method (now named to_s_without_quotes) and surround the results with, you guess it, quotes.
To use this you would either manually include the module in a class or, more along the lines of aspects, force the inclusion with some code like this:
MyClass.send(:include, QuoteToS)(As a side note, the use of unless method_defined?(:to_s_without_quotes) is to work-around a bug in Ruby 1.8.4 that causes an infinite recursion when using alias_method. [...])
So that's all very well and good but what happens when you need to do the same thing with [class] methods? The answer is, use
class << selfandextend. In my case, overriding the behaviour of ActiveRecord::Schema.define looks something like this:module ForeignKeyMigrations::Schema def self.included(base) base.extend(ClassMethods) base.class_eval do class << self alias_method :define_without_fk, :define unless method_defined?(:define_without_fk) alias_method :define, :define_with_fk end end end module ClassMethods def define_with_fk(info={}, &block) ... define_without_fk(info, &block) end end endHere, the use of base.extend causes all the methods defined within the module ClassMethods--an aribitrary name used by convention in most if not all the rails code I've ever seen—to be added as [class] methods on the class. Then, surrounding the alias_method calls within a class << self causes them to be executed in [class] context.
Again, to have this code mixed-in to the existing ActiveRecord::Schema class looks like this:
ActiveRecord::Schema.send(:include, ForeignKeyMigrations::Schema)
