【问题标题】:What is the difference between `try` and `&.` (safe navigation operator) in RubyRuby中的`try`和`&.`(安全导航运算符)有什么区别
【发布时间】:2017-08-22 19:18:04
【问题描述】:

这是我的代码:

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 #<Order:0x007f83b9efc970>

我认为&amp;..try 的快捷方式,但我想我错了。有人可以指出我所缺少的正确方向吗?

我觉得它与红宝石无关。也许是葡萄?虽然我不明白它是怎么回事。

【问题讨论】:

  • 它们不一样,你可以阅读更多关于区别here

标签: ruby-on-rails ruby if-statement nomethoderror grape-api


【解决方案1】:

&amp;. 的作用类似于 #try!,而不是 #try

这里是#try!的描述(来自documentation):

同#try,但如果接收不为nil且未实现尝试过的方法,则会引发NoMethodError异常。

所以基本上它可以让你免于调用nil 上的方法,但是如果呈现了一个对象,它会像往常一样尝试调用它的方法。

引用来自 Rails 文档,因此需要强调 Ruby 不提供#try;它由 Rails 提供,或者更准确地说是 ActiveSupport。但是,safe navigation operator (&amp;.) 是 Ruby 2.3.0 中提供的语言功能。

【讨论】:

  • “所以基本上它可以让你免于在 nil 上调用方法”——这句话中的“it”指的是什么?
  • @Jason:“它”是安全导航操作员或尝试!。
【解决方案2】:

我来晚了一点,其他答案已经涵盖了它是如何工作的,但我想添加一些其他答案没有涵盖的内容。

您的问题是 Ruby 中的 try&amp;. 有什么区别。 Ruby 是这里的关键词。

最大的不同是try在Ruby中不存在,它是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

&amp;. 是 Ruby 标准库的一部分,因此可用于任何 Ruby 项目,而不仅仅是 Rails。

【讨论】:

  • 因此,如果您的代码可能在纯 Ruby 中运行,您应该使用foo.try(:try, ...) 以确保安全。
  • 对不起@mwfearnley 但我不明白你的评论。如果代码是纯 Ruby(即在 Rails 之外或不使用ActiveSupport),那么如果foo.try 会引发NoMethodError,那么做foo.try(:try...) 有什么意义?
  • @gasc 现在回过头来看我的评论,我不得不断定这是个玩笑,因为这个建议“显然”很糟糕。当然,如果你几乎可以肯定@ 987654332@ 会失败,那么你应该做foo.try(:try, :try...) 以更加安全..
  • ......我毁了这个笑话=(我的坏@mwfearnley
  • 在纯Ruby中,foo!foo,没有#try
【解决方案3】:

除了上面的答案,我再补充一些例子。1

account = Account.new(owner: Object.new)

account.try(:owner).try(:address)
# => nil

account&.owner&.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`

account.try!(:owner).try!(:address)
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`

正如我们所见,try 不检查接收者是否响应给定的方法。而try!&amp;. 的行为相同。如果接收者响应address 方法,它们都将返回相同的结果。我更喜欢使用&amp;.,因为它看起来更干净。

有关安全导航运算符 (&.) 的更多信息,我发现此博客非常有帮助 https://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/

【讨论】:

    【解决方案4】:

    try 方法忽略了很多事情,它只是试一试,如果事情不成功,它就结束了。

    &amp; 条件导航选项将阻止对nil 对象的调用。其他任何事情都被认为是有效的,并将承担全部后果,包括例外情况。

    【讨论】:

      猜你喜欢
      • 2016-03-18
      • 1970-01-01
      • 2022-06-10
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 2012-03-13
      • 2018-08-16
      • 2012-10-10
      相关资源
      最近更新 更多