这是我的代码:
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>
我认为&.
是.try
的捷径,但我想我错了。可能有人指出我正确的方向,我错过了什么?
我觉得这不是红宝石相关的。葡萄可能吗?虽然我不知道它是怎么回事。
答案 0 :(得分:34)
&.
的作用类似于#try!
,而不是#try
。
以下是#try!
(来自documentation)的说明:
与#try相同,但如果接收不是nil并且没有实现尝试过的方法,则会引发NoMethodError异常。
所以基本上它可以让你免于调用nil
上的方法,但是如果出现一个对象,它会像往常一样调用它的方法。
引用来自Rails文档,因此重要的是要强调
Ruby没有提供#try
;它由Rails提供,或者更准确地说是ActiveSupport。然而,safe navigation operator(&.
)是Ruby 2.3.0中提供的语言功能。
答案 1 :(得分:10)
try
方法忽略了很多东西,它只是给它一个镜头,并且如果事情不能解决,就把它称为一天。
&
条件导航选项仅阻止对nil
个对象的调用。其他任何内容都被视为有效,并将继续产生全部后果,包括例外情况。
答案 2 :(得分:3)
我到这里来的时候有点晚了,其他的答案已经涵盖了它的运作方式,但是我想补充其他答案没有涉及的内容。
您的问题询问 Ruby 中try
和&.
之间的区别是什么。 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
&.
是Ruby标准库的一部分,因此可用于任何Ruby项目,而不仅仅是Rails。
答案 3 :(得分:1)
在评论部分同意@Redithion
Ruby中的安全导航运算符(&。)
如果在nil对象上调用方法,则安全导航运算符将返回nil。在此之前,如果在nil对象上调用方法,则会引发如下错误。
$ nil.some_method
=> NoMethodError: undefined method 'some_method' for nil:NilClass
我们为什么需要安全导航?
很多时候,由于一些错误的输入值,我们没有得到对象。在这种情况下,如果我们继续调用具有对象的期望方法,那么如果对象变成nil对象,代码可能会中断。
为避免这种情况,引入了安全导航。这样可以确保即使调用该方法的对象为nil对象,我们的代码也不会中断。当我们很好地在方法调用失败时接收nil对象时,应使用此方法。
示例
假设您有一个拥有所有者的帐户,并且想要获取所有者的地址。如果您想安全起见并且不冒Nil错误的危险,则可以编写以下内容。
if account && account.owner && account.owner.address
...
end
这真的很冗长而且令人讨厌。 ActiveSupport包含try方法,该方法具有类似的行为(但有一些主要区别,稍后将讨论):
if account.try(:owner).try(:address)
...
end
它完成相同的事情-如果链中的某个值为nil,则返回地址或为nil。如果例如所有者设置为false,则第一个示例也可能返回false。
使用&。
我们可以使用安全导航操作符重写前面的示例:
account&.owner&.address
答案 4 :(得分:1)
除了上述答案之外,我还添加了一些示例。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!
和 &.
的行为相同。如果接收者响应 address
方法,它们都会返回相同的结果。我更喜欢使用 &.
,因为它看起来更干净。
有关安全导航操作符 (&.) 的更多信息,我发现此博客非常有用https://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/