Какой лучший способ проверить объект на ноль перед вызовом метода на нем? - PullRequest
6 голосов
/ 27 июня 2009

У меня есть вызов этого метода, я должен использовать ...

financial_document.assets.length

Но financial_document.assets может быть nil.

Я мог бы использовать ...

financial_document.assets.nil? ? '0' : financial_document.assets.length

Есть ли менее повторяющийся способ сделать это?

Ответы [ 11 ]

8 голосов
/ 27 июня 2009

Дейв В. Смит на правильном пути.

Проверьте это: http://www.nach -vorne.de / 2007/4/24 / attr_accessor-on-steroids

Одно простое решение будет выглядеть примерно так:

class FinancialDocument
  attr_accessor :assets
  def assets
    @assets ||= Array.new
  end
  ...
end
7 голосов
/ 27 июня 2009

Лично я бы использовал оператор or / ключевое слово:

(financial_document.assets or []).length

В любом случае, .length вызывается для массива, давая вам 0, если nil.

7 голосов
/ 27 июня 2009

Менее повторяющийся способ справиться с этим - убедиться, что financial_document.assets всегда является ненулевым объектом, организовав так, чтобы он содержал соответствующее значение часового типа (например, пустую коллекцию или специальный объект, который вырожден). поведение).

См. Шаблон нулевого объекта .

3 голосов
/ 27 июня 2009

Более общий способ решения этого класса проблем заключается в добавлении метода try в Object:

  ##
  #   @user.name unless @user.nil?
  # vs
  #   @user.try(:name)
  #
  def try(method, *args, &block)
    return nil unless method
    return nil if is_a?(NilClass) and [:id, 'id'].include?(method)
    self.send(method, *args, &block) if respond_to?(method)
  end

Я считаю, что в ruby ​​1.9 уже есть метод try для Object.

Тогда financial_document.assets.try(:length).to_i достигнет желаемого результата. Это потому что nil.to_i возвращает 0

3 голосов
/ 27 июня 2009

В таком случае я использую andand gem:

financial_document.assets.andand.length || 0
3 голосов
/ 27 июня 2009

Дело 1:

financial_document и assets имеют много отношений. В этом случае financial_document.assets всегда возвращает массив. Таким образом, financial_document.assets.size даст вам 0, если не найдена соответствующая дочерняя запись, и размер в противном случае.

Случай 2:

assets - это просто метод / атрибут в financial_document. Затем получите массив возврата метода assets, чтобы вы всегда могли вызвать .size для него. Так же, как указывал Джоэл.

1 голос
/ 01 апреля 2011

Вы можете сделать это без дополнительных драгоценных камней. Я использовал ||, andand, try, но следующее выглядит проще. Я думаю, что это рубиновый способ подтверждения нулевого объекта Дейва.

financial_document.assets.to_a.length
1 голос
/ 24 февраля 2011

financial_document.assets.try (: length) || 0

try - это метод, который будет вызывать метод объекта, если его не ноль, в противном случае просто вернуть ноль. И попробуйте методы nil всегда возвращать nil вместо того, чтобы выдавать исключение.

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

Это Ruby способ сделать это!

0 голосов
/ 27 июня 2009

Что-то в модели, которая возвращает 0 или длину. Это избавляет вас от необходимости делать что-то ценное с вашей точки зрения. Такие вещи обычно можно сделать в модели.

class FinancialDocument

  def assets_length
    assets.length.blank? 0 : assets.length
  end
end
0 голосов
/ 27 июня 2009

Вы можете сделать его немного короче:

financial_document.assets ? financial_document.assets.length : '0'

потому что

financial_document.assets == !financial_document.assets.nil?

но в целом ИМХО тут не менее повторяющийся путь, только различные обходные пути. (И это одна из вещей, которые мне не очень нравятся в Ruby.) Вы можете убедиться, что объекты не являются нулевыми (как предлагают другие люди) - но вы не можете делать это везде. Вы можете обернуть код нулевой проверки в вспомогательные методы или в блоки begin-rescue.

Например, вместо того, чтобы добавлять метод длины к объекту nil (который ИМХО грязный хак), я бы написал вспомогательный метод - "получатель длины":

def fd_length(financial_document)
  financial_document.assets ? financial_document.assets.length : '0'
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...