问题描述
在/rails/lib/rails.rb中,有一个用逻辑&&
运算符的习惯用法:
def root
application && application.config.root
end
这个成语是什么意思?似乎有一些控制流程,如果应用程序存在或类似的东西,只返回application.config.root?
解决方法
在ruby中,逻辑运算符是“惰性”。
请考虑以下内容:
def one
puts "Called method one"
false
end
def two
puts "Called method two"
true
end
puts "Calling one,then two:"
one && two
puts
puts "Calling two,then one:"
two && one
它给出以下输出:
Calling one,then two:
Called method one
Calling two,then one:
Called method two
Called method one
看看发生了什么事?当它调用one
并得到false
时,它根本不费心调用方法two
-因为它已经知道最终结果将是{{ 1}}。 (false
== false && false
== false && true
。)
现在让我们回顾一下您发布的原始代码:
false
如果def root
application && application.config.root
end
会怎样?这段代码根本不用费心评估右侧。自application == nil
起。
换句话说,这是一种安全措施。如果nil && literally_anything == nil
,则可以防止代码失败。它(不是完全,而是基本上)等同于编写以下代码:
application == nil
,
避免NoMethodError
在对计算结果为nil的表达式或不#respond_to吗的对象上调用方法时,Ruby代码会引发NoMethodError。一种特定的方法。较新版本的Ruby支持safe navigation operator来防止在NilClass实例上调用方法,而较早的代码通常需要这种类型的构造以避免引发异常。
在伪代码中:
define method "root":
if application does not evaluate to nil,then
invoke method config on application,then
invoke method root on application.config
在Ruby> = 2.3中,您可能将此方法重写为:
def root
application&.config.root
end
但是,在某些情况下,&.
并不完全等同于obj && obj.method
。前者只是防止在nil上调用方法。例如,如果application.nil?
和application.respond_to? :config
均为假,则在调用application&.config
时使用安全导航器仍会引发异常。
由于设置或使用了 application 变量的方式,是否需要在示例中进行逻辑AND操作,您还是希望保留传统习语或为了与Ruby早期版本向后兼容而保留必须在Rails代码库中进行调查。在任何情况下,示例中的逻辑AND均防止NoMethodError异常。
,根据广泛使用的红宝石样式指南https://github.com/rubocop-hq/ruby-style-guide#if-as-a-modifier,当您使用单行正文时,需要偏爱使用修饰符if/unless
。另一个不错的选择是使用控制流&&/||
(即您要问的内容)。
# bad
if some_condition
do_something
end
# good
do_something if some_condition
# another good option
some_condition && do_something