我似乎找不到办法做到这一点。我想做的就是尝试第一个语句,如果它是空的或null(在任何阶段)然后返回另一个。例如
a.b.c.blank? ? a.b.c : 'Fill here'
这导致我nil:NillClass
例外。有没有办法以简单的单线方式解决这个问题?
如果你有active_support
可用,你可以使用Object#try
:
a.try(:b).try(:c) or 'Fill here'
如果你没有这个,那么很容易用Object
来补充一个。这是active_support
中的代码,在你使用try
方法之前把它放在一些地方。
class Object
def try(*a, &b)
if a.empty? && block_given?
yield self
else
public_send(*a, &b) if respond_to?(a.first)
end
end
end
之后,您可以使用它:
a = nil
a.try(:b).try(:c).try(:nil?) #=> true
b = 1
b.try(:+, 2) #=> 3
默认情况下没有抛出nil:NilClass
异常。
a
或b
或c
可能是零,所以对于单行声明,您可以这样做:
# require this to use present?, not needed with rails
require 'active_support/all'
a.present? ? (a.b.present? ? (a.b.c.present? ? a.b.c : 'Fill here') : 'Fill here') : 'Fill here'
(这是三元表达式,不完全是if语句)
但这很难看,虽然如果你确定a
或a.b
永远不会是nil
,你可以删除部分表达式。
我使用present?
而不是blank?
来保持与你的表达相同的顺序。如果条件为真,则三元运算符计算第一个表达式,因此这可能是您的错误。
我需要允许使用presence
的ActiveSupport包做类似这样的事情:
require 'active_support'
require 'active_support/core_ext/object/blank'
a.presence && a.b.presence && a.b.c.presence || 'Fill here'
从Ruby 2.3.0(2015-12-25发布)开始,这可以使用save navigation operator
实现,类似于Groovy和Kotlin的null安全?
:
新方法调用语法,
object&.foo', method foo is called on
object'如果它不是nil。
# a as object { b: { c: 'foobar' } }
a&.b&.c&.empty? ? 'Fill here' : a.b.c #=> 'foobar'
nil&.b&.c&.empty? ? 'Fill here' : a.b.c #=> 'Fill here'
当他们被调用nil对象时,安全调用返回nil
。这就是为什么上面例子中的第二个案例评估为nil
,因此false
。
来源:NEWS for Ruby 2.3.0 (Feature #11537)
另见:What is the difference between try
and &.
(safe navigation operator) in Ruby