Using Ruby 1.8.6 / Rails 2.3.2
I am noticing that any method called on any of my ActiveRecord model classes is returning nil
instead of a NoMethodError. Besides annoying, this is breaking the dynamic finders (find_by_name
, find_by_id
, etc.) because they always return nil
even where records exist. Standard classes that don't derive from ActiveRecord::Base aren't affected.
Is there a way to track down what is intercepting method_missing before ActiveRecord::Base?
UPDATE:
After switching to 1.8.7, I have found (thanks to @MichaelKohl) that the will_paginate plugin is handling method_missing first. But will_paginate has been around in our system (unaltered) for quite a while and the culprit must be something later up the chain. Any ideas how to see what comes next in this chain?
UPDATE:
It turned out that there was a gem (annotate-2.4.0) that was monkey patching ActiveRecord::Base#method_missing
as a blank method. Uninstalling the gem solved my problem. Although none of the answers given actually found the problem, the answer by @Yanhao came closest as it only needed a minor tweak to discover the offending aliased method
I think @Sebi's answer is helpful, but I'd like to improve it like this:
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'
}
The result is like this:
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
You could try this : In rails console
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
The last line of the output should be the culprit.
Have you tried TheModel.method(:method_missing).owner
? I have no Rails console available, but look at this example:
>> class MyString < String ; end #=> nil
>> MyString.new.method(:method_missing).owner #=> BasicObject
As you can see this shows you the closest method_missing
definition in the ancestors chain.
Edit: sorry, didn't take into account your old Ruby version. In that case, go with @aNoble's suggestion, and also look at How to find where a method is defined at runtime? in this context.
Use the Ruby debugger, insert a breakpoint before an ActiveRecord
-call that returns nil
and start stepping your way through. I think this is superior to all other solutions discussed here, because it's easy to understand what's really going on and gives you a more thorough understanding of the call hierarchy that causes your problem. Apart from that, it's quite an universal skill that helps solving many other problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With