Why is try throwing an error? Doesnt that defeat the whole purpose? Maybe its just in the console?
ruby-1.9.2-p180 :101 > User.first.try(:something)
NoMethodError: undefined method `something' for #<User:0x000001046ad128>
from /Users/me/.rvm/gems/ruby-1.9.2-p180/gems/activemodel-3.0.10/lib/active_model/attribute_methods.rb:392:in `method_missing'
from /Users/me/.rvm/gems/ruby-1.9.2-p180/gems/activerecord-3.0.10/lib/active_record/attribute_methods.rb:46:in `method_missing'
from (irb):101
from /Users/me/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.10/lib/rails/commands/console.rb:44:in `start'
from /Users/me/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.10/lib/rails/commands/console.rb:8:in `start'
from /Users/me/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.10/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
EDIT:
Thanks guys, now I get it.
Is there a way to do what I wanted without doing using respond_to?
, such that User.try(:something)
returns nil
instead of throwing the error?
This is what try does
So, let's say you setup
@user
in your controller but you didn't instantiate it then@user.try(:foo) => nil
instead ofThe important point here is that try is an instance method. It also doesn't return nil if the object you try on isn't nil.
Rails 3
You misunderstand how
try
works, from the fine manual:And the version of
try
that is patched intoNilClass
:So
try
doesn't ignore your attempt to call a non-existent method on an object, it ignores your attempt to call a method onnil
and returnsnil
instead of raising an exception. Thetry
method is just an easy way to avoid having to check fornil
at every step in a chain of method calls.Rails 4
The behavior of
try
has changed in Rails 4 so now it:So now
try
takes care of both checks at once. If you want the Rails 3 behavior, there istry!
:I know this is old, but it may help somebody else, because this is the first thing that popped up when I Googled this issue. I "borrowed" the code for try and implemented my own try_method method which acts just like try, except that it first checks to see if the method exists before calling send. I implemented this in Object and put it in an initializer, and I can now call it on any object.