简化Rails中的多个nil检查

时间:2012-01-04 04:16:33

标签: 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?

谢谢。

10 个答案:

答案 0 :(得分:4)

Rails有object.try(:method)

if @parent.try(:child).try(:grand_child).try(:attribute).present?
   do_something

http://api.rubyonrails.org/classes/Object.html#method-i-try

答案 1 :(得分:3)

您可以使用Object#andand

有了它,您的代码将如下所示:

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

答案 2 :(得分:3)

您可以通过将中间值分配给某个局部变量来稍微减少它:

if a = @parent.child and a = a.grandchild and a.attribute

答案 3 :(得分:2)

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

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

但是使用andand可能更好,或ick,我非常喜欢并且有trymaybe等方法。

答案 4 :(得分:0)

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

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

或者,创建has_many :through关系,以便@parent可以转到grandchild,以便您可以使用:

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

注意:present?不仅适用于nil,还会检查空值''。如果只是零检查,你可以@parent.grandchild.attribute

答案 5 :(得分:0)

你只能抓住例外:

begin
  do something with parent.child.grand_child.attribute
rescue NoMethodError => e
  do something else
end

答案 6 :(得分:0)

我想你可以使用delegate方法做到这一点,因为你会像......

@parent.child_grand_child_attribute.present?

答案 7 :(得分:0)

您好,您可以在此处使用带有救援选项的标志变量

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

if flag
do_something
end

答案 8 :(得分:0)

你可以这样做:

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

来源:http://codon.com/refactoring-ruby-with-monads

答案 9 :(得分:0)

所有这些答案都是过时的,所以我认为我应该分享更多现代选择。

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

@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)

如果子代,孙代或属性不存在,则这两种方法都会正常返回nil