Ruby on rails 简化Rails中的多个nil检查

Ruby on rails 简化Rails中的多个nil检查,ruby-on-rails,ruby,syntax,Ruby On Rails,Ruby,Syntax,我应该怎样写: if @parent.child.grand_child.attribute.present? do_something 无需繁琐的零检查以避免异常: if @parent.child.present? && @parent.child.grandchild.present? && @parent.child.grandchild.attribute.present? begin do something with parent.chi

我应该怎样写:

if @parent.child.grand_child.attribute.present?
  do_something
无需繁琐的零检查以避免异常:

if @parent.child.present? && @parent.child.grandchild.present? && @parent.child.grandchild.attribute.present?
begin
  do something with parent.child.grand_child.attribute
rescue NoMethodError => e
  do something else
end
谢谢。

你可以用

使用它,您的代码将如下所示:

if @parent.andand.child.andand.grandchild.andand.attribute

为了好玩,您可以使用折叠:

[:child, :grandchild, :attribute].reduce(@parent){|mem,x| mem = mem.nil? ? mem : mem.send(x) } 

但是使用and可能更好,或者,我非常喜欢and,并且有类似于
try
maybe
的方法,您可以通过将中间值分配给某些局部变量来稍微减少and:

if a = @parent.child and a = a.grandchild and a.attribute
Rails具有
对象。请尝试(:方法)


如果要检查的属性始终相同,请在@parent中创建一个方法

def attribute_present?
  @parent.child.present? && @parent.child.grandchild.present? && @parent.child.grandchild.attribute.present?
结束

或者,创建
具有多个:通过
关系,以便
@父项
可以访问
孙项
,以便您可以使用:

@parent.grandchild.try(:attribute).try(:present?)

注意:
present?
不仅仅用于nil,它还检查空白值,
'
。您可以只执行
@parent.granner.attribute
,如果只是执行nil检查

您可以捕获异常:

if @parent.child.present? && @parent.child.grandchild.present? && @parent.child.grandchild.attribute.present?
begin
  do something with parent.child.grand_child.attribute
rescue NoMethodError => e
  do something else
end

我想你可以使用
委托
方法来做,结果你会得到类似的结果

@parent.child_grand_child_attribute.present?

您好,我想您可以在这里使用带有rescue选项的标志变量

flag = @parent.child.grand_child.attribute.present? rescue false

if flag
do_something
end
您可以这样做:

Optional = Struct.new(:value) do
  def and_then(&block)
    if value.nil?
      Optional.new(nil)
    else
      block.call(value)
    end
  end

  def method_missing(*args, &block)
    and_then do |value|
      Optional.new(value.public_send(*args, &block))
    end
  end
end
您的支票将变成:

if Optional.new(@parent).child.grand_child.attribute.present?
  do_something

资料来源:

所有这些答案都是老生常谈,所以我想我应该分享更现代的选择

如果您获得的关联可能不存在:

@parent&.child&.grand_child&.attribute
hash = {
 parent_key: {
   some_other_key: 'a value of some sort'
 },
 different_parent_key: {
   child_key: {
     grand_child: {
       attribute: 'thing'
     }
   }
 }
}
hash.dig(:parent_key, :child_key, :grandchild_key)
如果要访问可能不存在的密钥的哈希:

@parent&.child&.grand_child&.attribute
hash = {
 parent_key: {
   some_other_key: 'a value of some sort'
 },
 different_parent_key: {
   child_key: {
     grand_child: {
       attribute: 'thing'
     }
   }
 }
}
hash.dig(:parent_key, :child_key, :grandchild_key)

如果孩子、孙子或属性不存在,这两个选项中的任何一个都将优雅地返回零

谢谢,塞尔吉奥。我在这里学到了一些新东西。只是想知道是否有更自然的方式来表达它。@AdamNYC如果你期待Ruby自然的方式,那么你不应该把这个问题标记为
Ruby on rails
,因为它已经
try
,这不是Ruby自然的。谢谢sawa。无论是Ruby还是Rails对我来说都是不错的。我本来打算提到Ick,但我认为在这种情况下这是一种过分的做法:-)很可能,但它看起来很漂亮(尤其是
):-)谢谢Iain和Sergio。Ick对我来说也是新的,似乎我得到了比我要求的更好的答案。:-)您正在进行
nil
检查吗?那么你不需要
在场吗?
。我认为这相当于
如果@parent.child.nil?还有@parent.child.granchild.nil。我说的对吗?No
present
用于检查它是
nil
还是
空的
。你通常不需要
nil?
,除非你想区分
nil
false
。对。感谢您的澄清。至少您应该将这些知识传递给帮助者。我也经常使用这些知识,通常出于某种原因用于数据库查询,例如:
if(u=User[id])&&u.admin?
。。。但对于两个以上的人,我使用像ick或andand这样的库,否则它可能会开始看起来很混乱+这是一个非常有用的提示。有更多信息的文章