简化Rails中的多重nil检查

时间:2021-10-08 11:46:20

How should I write:

我该如何写:

if @parent.child.grand_child.attribute.present?
  do_something

without cumbersome nil checkings to avoid exception:

没有繁琐的nil检查以避免异常:

if @parent.child.present? && @parent.child.grandchild.present? && @parent.child.grandchild.attribute.present?

Thank you.

谢谢你!

9 个解决方案

#1


4  

Rails has object.try(:method):

Rails object.try(方法):

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

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

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

#2


3  

You could use Object#andand.

您可以使用# andand对象。

With it your code would look like this:

有了它,你的代码会变成这样:

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

#3


3  

You can slightly reduce it by assigning the intermediate values to some local variable:

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

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

#4


2  

For fun, you could use a fold:

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

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

but using andand is probably better, or ick, which I like a lot and has methods like try and maybe.

但是使用andand可能更好,或者是ick,我很喜欢它,它有try和maybe这样的方法。

#5


0  

If the attribute you are checking is always the same, create a method in @parent.

如果要检查的属性总是相同的,那么在@parent中创建一个方法。

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

end

结束

Alternatively, create has_many :through relationship so that @parent can get to grandchild so that you can use :

或者,创建has_many:通过关系,以便@parent可以到达孙子,以便您可以使用:

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

Note: present? is not just for nil, it also checks for blank values, ''. You can just do @parent.grandchild.attribute if it's just nil checking

注:现在?不仅是nil,它还检查空值。你可以做@parent.grandchild。属性,如果只是nil检查

#6


0  

You coult just catch the exception:

你不能只抓住例外:

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

#7


0  

I suppose you can do it using a delegate method as a result you'll have sth like

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

@parent.child_grand_child_attribute.present?

#8


0  

Hi Think you can use a flag variable here with rescue option

你好,你可以在这里使用一个标志变量和营救选项

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

if flag
do_something
end

#9


0  

You could do this:

你可以这样做:

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

Your check would become:

你的检查将成为:

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

Source: http://codon.com/refactoring-ruby-with-monads

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

#1


4  

Rails has object.try(:method):

Rails object.try(方法):

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

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

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

#2


3  

You could use Object#andand.

您可以使用# andand对象。

With it your code would look like this:

有了它,你的代码会变成这样:

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

#3


3  

You can slightly reduce it by assigning the intermediate values to some local variable:

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

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

#4


2  

For fun, you could use a fold:

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

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

but using andand is probably better, or ick, which I like a lot and has methods like try and maybe.

但是使用andand可能更好,或者是ick,我很喜欢它,它有try和maybe这样的方法。

#5


0  

If the attribute you are checking is always the same, create a method in @parent.

如果要检查的属性总是相同的,那么在@parent中创建一个方法。

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

end

结束

Alternatively, create has_many :through relationship so that @parent can get to grandchild so that you can use :

或者,创建has_many:通过关系,以便@parent可以到达孙子,以便您可以使用:

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

Note: present? is not just for nil, it also checks for blank values, ''. You can just do @parent.grandchild.attribute if it's just nil checking

注:现在?不仅是nil,它还检查空值。你可以做@parent.grandchild。属性,如果只是nil检查

#6


0  

You coult just catch the exception:

你不能只抓住例外:

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

#7


0  

I suppose you can do it using a delegate method as a result you'll have sth like

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

@parent.child_grand_child_attribute.present?

#8


0  

Hi Think you can use a flag variable here with rescue option

你好,你可以在这里使用一个标志变量和营救选项

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

if flag
do_something
end

#9


0  

You could do this:

你可以这样做:

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

Your check would become:

你的检查将成为:

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

Source: http://codon.com/refactoring-ruby-with-monads

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