特異メソッドを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
同じような現象でハマッた方も多いのではないだろうか?