Упростите множественную проверку на ноль в Rails - PullRequest
2 голосов
/ 04 января 2012

Как мне написать:

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

без громоздких нулевых проверок, чтобы избежать исключения:

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

Спасибо.

Ответы [ 9 ]

4 голосов
/ 04 января 2012

Рельсы имеют 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

3 голосов
/ 04 января 2012

Вы можете немного уменьшить его, присвоив промежуточные значения некоторой локальной переменной:

if a = @parent.child and a = a.grandchild and a.attribute
3 голосов
/ 04 января 2012

Вы можете использовать Object # andand .

С ним ваш код будет выглядеть так:

if @parent.andand.child.andand.grandchild.andand.attribute
2 голосов
/ 04 января 2012

Для удовольствия вы можете использовать фолд:

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

, но лучше использовать andand, или ick , который мне очень нравится и имеет методы типа trymaybe.

0 голосов
/ 04 октября 2014

Вы можете сделать это:

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

0 голосов
/ 27 августа 2013

Привет. Думаю, вы можете использовать здесь флаговую переменную с опцией спасения

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

if flag
do_something
end
0 голосов
/ 04 января 2012

Полагаю, вы можете сделать это, используя метод delegate, в результате вы получите

@parent.child_grand_child_attribute.present?
0 голосов
/ 04 января 2012

Вы можете просто поймать исключение:

begin
  do something with parent.child.grand_child.attribute
rescue NoMethodError => e
  do something else
end
0 голосов
/ 04 января 2012

Если атрибут, который вы проверяете, всегда один и тот же, создайте метод в @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, если это просто проверка на ноль

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...