l'essentiel est invisible pour les yeux

Sunday, April 08, 2007

[ruby] 特異メソッドに別名をつけて退避する

特異メソッドをalias_methodを使用して別名をつけようとするとエラーになる。
だが、同じブロック内でrespond_to?(:find)を実行するとtrueが返される。


undefined method `find' for class `ActiveRecord::Base' (NameError)



module EffectiveRails
module ActiveRecord
def self.included(klass)
klass.send ClassMethods
klass.class_eval do
p respond_to?(:find) # => true
alias_method_chain :find, :explain
end
end

module ClassMethods
def find_with_explain(*args)
# hogehoge
find_without_explain(*args)
end
end
end
end

ActiveRecord::Base.class_eval do
include EffectiveRails::ActiveRecord
end



Rubyの少々ややこしいクラスとオブジェクトの仕組みによるものだが、特異メソッドに別名をつけて退避したい場合は、alias_method (_chain)メソッドではなくてaliasをinstance_evalのブロック内で使用するとよい。


module EffectiveRails
module ActiveRecord
def self.included(klass)
klass.send ClassMethods
klass.instance_eval do
alias :find_without_explain :find
alias :find :find_with_explain
end
end

module ClassMethods
def find_with_explain(*args)
# hogehoge
find_without_explain(*args)
end
end
end
end

ActiveRecord::Base.class_eval do
include EffectiveRails::ActiveRecord
end



同じような現象でハマッた方も多いのではないだろうか?