Ruby中的`try`和`&.`(安全导航操作符)有什么区别?

这是我的代码:

class Order < Grape::Entity expose :id { |order, options| order.id.obfuscate } expose :time_left_to_review do |order, options| byebug order&.time_left_to_review # ERROR end expose :created_at { |order, options| order.last_transition.created_at } end # NoMethodError Exception: undefined method `time_left_to_review' for # 

我想&..try的捷径,但我想我错了。 可能有人指出我正确的方向,我错过了什么?

我觉得这不是ruby相关的。 葡萄可能吗? 虽然我不明白它是怎么回事。

&. 就像#try!一样#try! ,而不是#try

这里是#try!描述#try! (来自文件 ):

与#try相同,但如果接收不是nil并且未实现尝试的方法,则会引发NoMethodErrorexception。

所以基本上它可以避免你在nil上调用一个方法,但如果一个对象被呈现,它会像往常一样调用它的方法。

引用来自Rails文档,因此重要的是要强调Ruby不提供#try ,它是Rails,或者更准确地说是ActiveSupport。 安全导航操作员&. 是Ruby 2.3.0中提供的语言function。

try方法忽略了很多东西,它只是给它一个镜头,并且如果事情不能解决,就把它称为一天。

&条件导航选项阻止对nil对象的调用。 其他任何内容都被视为有效,并将继续产生全部后果,包括例外情况。

同意@Redithion的评论

Ruby中的安全导航操作符(&。)

脚本

想象一下,您拥有一个拥有owneraccount ,并且您希望获得所有者的address 。 如果你想要安全而不冒险出现Nil错误,你可以写下如下内容。

 if account && account.owner && account.owner.address ... end 

打字真的很冗长和烦人。 ActiveSupport包含具有类似行为的try方法(但几乎没有关键差异将在后面讨论):

 if account.try(:owner).try(:address) ... end 

它完成了同样的事情 – 它返回地址或者如果沿链的某个值nil则为nil 。 如果例如owner设置为false,则第一个示例也可能返回false。

使用&。

我们可以使用安全导航操作符重写上一个示例:

 account&.owner&.address 

更多例子

让我们更详细地比较所有三种方法。

 account = Account.new(owner: nil) # account without an owner account.owner.address # => NoMethodError: undefined method `address' for nil:NilClass account && account.owner && account.owner.address # => nil account.try(:owner).try(:address) # => nil account&.owner&.address # => nil 

到目前为止没有惊喜。 如果ownerfalse (在令人兴奋的糟糕代码世界中不太可能但不是不可能)会怎么样?

 account = Account.new(owner: false) account.owner.address # => NoMethodError: undefined method `address' for false:FalseClass ` account && account.owner && account.owner.address # => false account.try(:owner).try(:address) # => nil account&.owner&.address # => undefined method `address' for false:FalseClass` 

这是第一个惊喜 – &. 语法只跳过nil但识别为false! 它与s1 && s1.s2 && s1.s2.s3语法不完全等效。

如果所有者在场但未回复address怎么办?

 account = Account.new(owner: Object.new) account.owner.address # => NoMethodError: undefined method `address' for # account && account.owner && account.owner.address # => NoMethodError: undefined method `address' for #` account.try(:owner).try(:address) # => nil account&.owner&.address # => NoMethodError: undefined method `address' for #` 

下面的例子是混乱和nil&.nil? 应该回归true

使用&.时要小心&. 运算符并检查nil值。 请考虑以下示例:

 nil.nil? # => true nil?.nil? # => false nil&.nil? # => nil 

参考: 这里

我到这里来的时候有点晚了,其他的答案已经涵盖了它的工作方式,但我想补充一些其他答案没有涵盖的内容。

你的问题询问try&.之间有什么区别&.Ruby中 。 Ruby是这里的关键词。

最大的区别是Ruby中不存在try ,它是Rails提供的方法。 如果你在rails控制台中做这样的事情,你可以看到这个或你自己:

 [1, 2, 3].try(:join, '-') #=> "1-2-3" 

但是,如果您在irb控制台中执行相同的操作,您将获得:

 [1, 2, 3].try(:join, '-') NoMethodError: undefined method `try' for [1, 2, 3]:Array 

&. 是Ruby标准库的一部分,因此可以在任何Ruby项目中使用,而不仅仅是Rails。