Jwa*_*622 31 ruby ruby-on-rails-4
我正在读这个.使用它有什么好处:
user&.address&.state
Run Code Online (Sandbox Code Playgroud)
过度
user.try(:address).try(:state)
Run Code Online (Sandbox Code Playgroud)
我还是不明白.
Raf*_*ael 66
&.一般比短于try(...)根据具体情况,这可以使您的代码更具可读性.
&.是标准的Ruby,而不是try该方法try未在Ruby核心库中定义,而是在Rails库中定义.当您没有开发RoR Web应用程序但是正在编写例如小帮助程序脚本时,这将非常快速地相关.(例如,我更喜欢Ruby而不是Bash.)
&.使调试更容易如果调用不存在的方法,则安全遍历运算符将抛出错误.
>> "s"&.glubsch
NoMethodError: undefined method `glubsch' for "s":String
Run Code Online (Sandbox Code Playgroud)
只有nil它会表现得很宽松:
>> nil&.glubsch
=> nil
Run Code Online (Sandbox Code Playgroud)
该try方法将始终返回nil.
>> "s".try(:glubsch)
=> nil
Run Code Online (Sandbox Code Playgroud)
请注意,最新版本的Ruby和Rails就是这种情况.
现在想象一个名为glubschexists 的方法存在的场景.然后你决定重命名该方法但忘记在一个地方重命名它.(遗憾的是,红宝石会发生这种情况......)使用安全遍历操作符,您几乎会立即注意到错误(只要第一次执行该行代码).try然而,该方法很乐意为您提供a,nil并且您将nil在程序执行的下游某处获得相关错误.弄清楚这样的nil来自哪里可能很难.
如果不快速,很难与&.品牌调试比轻率地返回更容易nil用try.
编辑:还有变体try!(有一个爆炸)的行为与&.这方面相同.如果你不喜欢,请使用它&..
那会很奇怪.由于这将是一种意想不到的编程方式,请明确说明.例如,通过使用respond_to?和分支两个案例(已实现与否)来充实它们.
try封锁形式怎么样?可以将块传递给而不是方法名称try.该块将在接收器的上下文中执行; 并且在该区块内没有适用宽大处理.因此,只需一个方法调用,它的行为就会与之相同&..
>> "s".try{ glubsch }
NameError: undefined local variable or method `glubsch' for "s":String
Run Code Online (Sandbox Code Playgroud)
对于更复杂的计算,您可能更喜欢这种块形式而不是引入大量局部变量.例如一个链
foo.try{ glubsch.blam }.try{ bar }.to_s
Run Code Online (Sandbox Code Playgroud)
将允许foo要nil,但需要foo.glubsch返回非nil数值.然后,您可以以更简洁的方式对安全遍历运算符执行相同的操作:
foo&.glubsch.blam&.bar.to_s
Run Code Online (Sandbox Code Playgroud)
使用try块形式进行复杂的计算恕我直言,因为它会妨碍可读性.当您需要实现复杂的逻辑时,引入具有描述性名称的局部变量,并且可以使用a if来分支nil案例.您的代码将更易于维护.
HTH!
ror*_*rra 23
安全导航几乎比使用activesupport中的try方法快4倍
require 'active_support/all'
require 'benchmark'
foo = nil
puts Benchmark.measure { 10_000_000.times { foo.try(:lala) } }
puts Benchmark.measure { 10_000_000.times { foo&.lala } }
Run Code Online (Sandbox Code Playgroud)
产量
1.310000 0.000000 1.310000 ( 1.311835)
0.360000 0.000000 0.360000 ( 0.353127)
Run Code Online (Sandbox Code Playgroud)
我认为我们不应该比较这两件事,因为它们做了别的事情。
鉴于这个示例Person类
class Person
def name
"John"
end
end
Run Code Online (Sandbox Code Playgroud)
try如果您不确定对象上是否存在给定的方法,则应使用。
person = Person.new
person.name # => "John"
person.email # => NoMethodError: undefined method `email' for #<Person>
person.try(:email) # => nil
Run Code Online (Sandbox Code Playgroud)
如果你不知道,如果你调用你的方法的对象安全nagivation应使用在零或不
person = nil
person.name # => NoMethodError: undefined method `name' for nil:NilClass
person&.name # => nil
Run Code Online (Sandbox Code Playgroud)
人们经常混淆这两种方法,因为您可以使用try代替&.
person = nil
person.name # => NoMethodError: undefined method `name' for nil:NilClass
person&.name # => nil
person.try(:name) # => nil
Run Code Online (Sandbox Code Playgroud)
但是你不能用&.代替try
person = Person.new
person.name # => "John"
person.email # => NoMethodError: undefined method `email' for #<Person>
person.try(:email) # => nil
person&.email # NoMethodError: undefined method `email' for #<Person>
Run Code Online (Sandbox Code Playgroud)