在/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
——因为它已经知道最终结果将是false
。(false && false
=false && true
=false
。(
现在让我们回顾一下您发布的原始代码:
def root
application && application.config.root
end
如果application == nil
会发生什么?此代码甚至不需要评估右手边。由于CCD_ 10。
换句话说,这是一个安全的警卫。如果application == nil
。它(不是确切地,但基本上(相当于写这个:
def root
return nil if application == nil
application.config.root
end
根据广泛使用的ruby样式指南,https://github.com/rubocop-hq/ruby-style-guide#if-作为修饰符,当你有一个单行体时,需要更喜欢使用修饰符if/unless
。另一个好的选择是使用控制流&&/||
(即您所询问的内容(。
# bad
if some_condition
do_something
end
# good
do_something if some_condition
# another good option
some_condition && do_something
避免NoMethodError
Ruby代码在对计算结果为nil的表达式或不#responsd_to的对象调用方法时,可能会抛出NoMethodError?一种特殊的方法。虽然较新版本的Ruby支持安全导航运算符来防止在NilClass实例上调用方法,但较旧的代码通常需要这种类型的构造来避免引发异常。
在peudocod:
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
都为false,那么在调用application&.config
时使用安全导航器仍然会引发异常。
您的示例中的逻辑AND是否是必要的,因为应用程序变量是如何设置或使用的,只是一个遗留习惯用法,还是为了与早期版本的Ruby向后兼容而保留,您必须在Rails代码库中进行研究。在任何情况下,示例中的逻辑AND都可以防止NoMethodError异常