Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
859 views
in Technique[技术] by (71.8m points)

rails < 4.0 "try" method throwing NoMethodError?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Rails 3

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 Ruby Object#send does.

Unlike that method however, a NoMethodError exception will not be raised and nil will be returned instead, if the receiving object is a nil object or NilClass.

And the version of try that is patched into NilClass:

try(*args)
Calling try on nil always returns nil.

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.


Rails 4

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 returns nil 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 a NoMethodError exception if the receiving [sic] is not nil and does not implemented [sic] the tried method.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...