使用Ruby 1.8.6 / Rails 2.3.2
我注意到在我的任何ActiveRecord模型类上调用的任何方法都返回nil
而不是NoMethodError。除了烦人之外,这会破坏动态查找器(find_by_name
,find_by_id
等),因为即使存在记录,它们也始终返回nil
。不从ActiveRecord :: Base派生的标准类不受影响。
有没有办法在ActiveRecord :: Base之前找到拦截method_missing的内容?
更新
切换到1.8.7后,我发现(感谢@MichaelKohl)will_paginate插件首先处理method_missing。但是will_paginate在我们的系统中已经存在了很长一段时间(并且没有改变),罪魁祸首必须是后来的链接。任何想法如何看待这个链中的下一步?
更新
事实证明,有一个gem(annotate-2.4.0)是猴子修补ActiveRecord::Base#method_missing
作为空白方法。卸载gem解决了我的问题。虽然没有给出的答案实际上找到了问题,但@Yanhao的答案最接近,因为它只需要一个小调整来发现有问题的别名方法
答案 0 :(得分:4)
我认为@Sebi的答案很有帮助,但我想像这样改进它:
set_trace_func proc { |event, file, line, id, binding, classname|
printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname if id.to_s == 'method_missing'
}
结果如下:
ruby-1.8.7-p334 :036 > SomeModel.some_missing_method
call /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1873 method_missing ActiveRecord::Base
line /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1874 method_missing ActiveRecord::Base
line /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1874 method_missing ActiveRecord::Base
line /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1981 method_missing ActiveRecord::Base
line /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1998 method_missing ActiveRecord::Base
c-call /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1998 method_missing Kernel
raise /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1998 method_missing ActiveRecord::Base
c-return /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1998 method_missing Kernel
return /Users/.../.rvm/gems/ruby-1.8.7-p334/gems/activerecord-2.3.12/lib/active_record/base.rb:1998 method_missing ActiveRecord::Base
答案 1 :(得分:3)
你可以试试这个: 在rails控制台
set_trace_func proc{ |event, file, line, id, binding, classname|
printf("%8s %s:%-2d %10s %8s\n", event, file, line, id, classname) if file =~ /my_app_name/ and event == 'return' #show only interesting files
}
MyModel.non_existing_method
输出的最后一行应该是罪魁祸首。
答案 2 :(得分:2)
你试过TheModel.method(:method_missing).owner
吗?我没有可用的Rails控制台,但请看这个例子:
>> class MyString < String ; end #=> nil
>> MyString.new.method(:method_missing).owner #=> BasicObject
如您所见,这显示了祖先链中最接近的method_missing
定义。
编辑:抱歉,没有考虑到您的旧Ruby版本。在这种情况下,请使用@ aNoble的建议,并在此上下文中查看How to find where a method is defined at runtime?。
答案 3 :(得分:2)
使用Ruby debugger,在ActiveRecord
之前插入一个断点 - 调用返回nil
并开始踩踏。我认为这优于此处讨论的所有其他解决方案,因为它很容易理解实际发生的事情,并让您更全面地了解导致问题的调用层次结构。除此之外,这是一项非常普遍的技能,有助于解决许多其他问题。
答案 4 :(得分:0)
在Rails控制台中试试这个:
MyModel.method(:method_missing)
当然,用您应用中的实际模型替换MyModel
。它应该告诉哪个类定义了method_missing
方法。如果你正在使用Ruby 1.9,你甚至可以MyModel.method(:method_missing).source_location
来获取确切的文件和行。