Ruby 为什么安全导航比使用try-in-Rails更好?
我在看书。使用此功能有什么好处:Ruby 为什么安全导航比使用try-in-Rails更好?,ruby,ruby-on-rails-4,Ruby,Ruby On Rails 4,我在看书。使用此功能有什么好处: user&.address&.state 结束 我还是不明白。(1)&。通常比try(…)短。 根据场景的不同,这可以使代码更具可读性 (2) &.是标准的Ruby,而不是try 方法try不是在Ruby核心库中定义的,而是在Rails库中定义的。当您不是在开发RoR web应用程序,而是在编写小助手脚本时,这将很快变得相关。 (例如,我更喜欢Ruby而不是Bash。) (3) &.使调试更容易 如果调用不存在的方法,安全遍历操作符将抛出错误
user&.address&.state
结束
我还是不明白。(1)&。
通常比try(…)短。
根据场景的不同,这可以使代码更具可读性
(2) &.
是标准的Ruby,而不是try
方法try
不是在Ruby核心库中定义的,而是在Rails库中定义的。当您不是在开发RoR web应用程序,而是在编写小助手脚本时,这将很快变得相关。
(例如,我更喜欢Ruby而不是Bash。)
(3) &.
使调试更容易
如果调用不存在的方法,安全遍历操作符将抛出错误
>> "s"&.glubsch
NoMethodError: undefined method `glubsch' for "s":String
只有在nil
上,其行为才会宽大:
>> nil&.glubsch
=> nil
try
方法将始终返回nil
>> "s".try(:glubsch)
=> nil
注意,最新版本的Ruby和Rails就是这样
现在想象一个场景,其中存在一个名为glubsch
的方法。然后,您决定重命名该方法,但忘记在一个位置重命名它。(遗憾的是,ruby可能会出现这种情况……)使用安全遍历操作符,您几乎会立即注意到错误(只要该行代码第一次执行)。然而,try
方法将愉快地为您提供一个nil
,并且您将在程序执行的下游某处得到一个与nil
相关的错误。有时,弄清楚这样一个nil
的来源可能很困难
使用&.
快速而艰难地失败比使用try
轻松地返回nil
更容易调试
编辑:还有变体try代码>(砰的一声)在这方面的行为与&.
相同。如果您不喜欢&.
,请使用该选项
>> "s".try{ glubsch }
NameError: undefined local variable or method `glubsch' for "s":String
(4) 如果我不在乎方法是否实现了呢?
那会很奇怪。由于这是一种意想不到的编程方式,请明确说明。例如,使用respond\u to?
充实这两个案例(实施与否),并将其分支
(5) 试试的块格式怎么样?
块可以传递给try
,而不是方法名。该块将在接收器的上下文中执行;在街区内,也没有宽大处理。因此,只需一个方法调用,它的行为实际上与&.
相同
>> "s".try{ glubsch }
NameError: undefined local variable or method `glubsch' for "s":String
对于更复杂的计算,与引入大量局部变量相比,您可能更喜欢这种块形式。例如,一系列
foo.try{ glubsch.blam }.try{ bar }.to_s
将允许foo
为nil
,但要求foo.glubsch
返回非nil
值。然后,您可以以更简洁的方式对安全遍历操作符执行相同的操作:
foo&.glubsch.blam&.bar.to_s
但是,使用try
的块形式进行复杂的计算是一种代码味道,因为它妨碍了可读性。当您需要实现复杂的逻辑时,引入带有描述性名称的局部变量,并可能使用if
来分支nil
案例。您的代码将更易于维护
嗯 (6)速度
安全导航的速度几乎是使用try方法的4倍
输出
1.310000 0.000000 1.310000 ( 1.311835)
0.360000 0.000000 0.360000 ( 0.353127)
我不认为我们应该比较这两件事,因为他们做了其他的事情
给出这个例子Person
class
班级人员
定义名称
“约翰”
结束
结束
尝试
如果不确定对象上是否存在给定方法,则应使用try
person=person.new
person.name#=>“John”
person.email#=>命名错误:未定义的方法“email”#
person.try(:email)#=>nil
&.
如果不确定调用方法的对象是否为零,则应使用安全Nagiviation
person=nil
person.name#=>NoMethodError:nil:NilClass的未定义方法“name”
人名#=>零
它们不能互换使用
人们经常混淆这两种方法,因为您可以使用try
而不是&。
person=nil
person.name#=>NoMethodError:nil:NilClass的未定义方法“name”
人名#=>零
person.try(:name)#=>nil
但是您不能使用&.
而不是try
person=person.new
person.name#=>“John”
person.email#=>命名错误:未定义的方法“email”#
person.try(:email)#=>nil
人员和.email#命名错误:未定义的方法“email”#
下面是我今天的非建设性评论:感谢您没有使用foo
作为默认变量glubsch
更有趣。响应很老,但只是一个注释,在最后一点上,表示try
版本和&.
版本的行为不一样。例如,当foo为nil
:try version将导致nil.to_
,而&。
version将尝试调用blam
onnil
并提出一个命名标准。事实上,具有完整ruby的真正相等的版本应该更像foo&.yield\u self{|foo | foo.glubsch.blam}如果不考虑NIOFor的错误FO,就可以考虑ToSo< <代码>或更可读:<代码> Fo& & Fo.GubsCh。BLAM & Bar。toys这个例子确实是错误的。谢谢你指出这一点,@firetonton。我将把它放在这里提醒大家,复杂的方法调用链是维护的噩梦。在我的机器上,它似乎快了3倍,但当foo
实际上不是零时,您忘记了测试用例。因此,我编写了以下基准测试:对于非nil对象,&
似乎比try
快8倍
1.310000 0.000000 1.310000 ( 1.311835)
0.360000 0.000000 0.360000 ( 0.353127)