rails <4.0“ try”方法抛出NoMethodError?

问题描述 投票:24回答:3

为什么要尝试引发错误?那会失败吗?也许只是在控制台上?

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>'

编辑:

谢谢,现在我明白了。

是否有一种无需使用respond_to?就可以完成我想做的事情的方法,例如User.try(:something)返回nil而不是抛出错误?

ruby-on-rails rails-activerecord nomethoderror
3个回答
56
投票

Rails 3

您从try误解了fine manual的工作原理:

try(* a,&b)调用由symbol方法标识的方法,并向其传递任何参数和/或指定的块,就像常规Ruby Object#send一样。

但是,与该方法不同,如果接收对象是NoMethodError对象或nil,则不会引发nil异常,而是返回NilClass

以及try that is patched into NilClass的版本:

try(* args)try上调用NilClass总是返回try

因此nil不会忽略您尝试在对象上调用不存在的方法,而是会忽略您尝试在nil上调用方法并返回try而不是引发异常的尝试。 nil方法是避免在方法调用链的每个步骤中都必须检查nil的简便方法。


Rails 4

try的行为已在Rails 4中更改,所以现在它:

[与nil一样,调用其名称作为第一个参数的公共方法,不同之处在于,如果接收方不响应,则调用返回try,而不引发异常。

所以现在public_send同时处理两项检查。如果您想使用Rails 3,可以使用nil

try相同,但是如果接收方[sic]不是try!并且未实现[sic]尝试过的方法,则会引发try!异常。


8
投票

这是尝试做的

调用由symbol方法标识的方法,并将其传递给参数和/或指定的块,就像常规的Ruby对象#发送发送。但是,与该方法不同的是,NoMethodError如果该异常不会引发,则将返回nil。接收对象是nil对象或NilClass。

所以,假设您在控制器中设置了try,但是您没有实例化它,然后是NoMethodError而不是

nil

这里的重点是try是一个实例方法。也@user


5
投票

我知道这很旧了,但是可能会对其他人有所帮助,因为这是我搜索此问题时弹出的第一件事。我“借用了” try的代码,并实现了自己的try_method方法,该方法的作用与try相似,只是它先检查该方法是否存在,然后再调用send 。我在Object中实现了它,并将其放在初始化程序中,现在可以在任何对象上调用它。

@user.try(:foo)
 => nil
© www.soinside.com 2019 - 2024. All rights reserved.