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?
You misunderstand how try
works, from the fine manual:
try(*a, &b)
Invokes the method identified by the symbol method, passing it any arguments and/or the block specified, just like the regular RubyObject#send
does.Unlike that method however, a
NoMethodError
exception will not be raised andnil
will be returned instead, if the receiving object is anil
object orNilClass
.
And the version of try
that is patched into NilClass
:
try(*args)
Callingtry
onnil
always returnsnil
.
So try
doesn't ignore your attempt to call a non-existent method on an object, it ignores your attempt to call a method on nil
and returns nil
instead of raising an exception. The try
method is just an easy way to avoid having to check for nil
at every step in a chain of method calls.
The behavior of try
has changed in Rails 4 so now it:
Invokes the public method whose name goes as first argument just like
public_send
does, except that if the receiver does not respond to it the call returnsnil
rather than raising an exception.
So now try
takes care of both checks at once. If you want the Rails 3 behavior, there is try!
:
Same as
try
, but will raise aNoMethodError
exception if the receiving [sic] is notnil
and does not implemented [sic] the tried method.