Что лучший путь состоит в том, чтобы проверить на нулевой объект прежде, чем назвать метод на нем?

Решение для тех, у кого возникли проблемы после перехода на KitKat:

«Это позволит получить путь к файлу от MediaProvider, DownloadsProvider и ExternalStorageProvider, а также вернуться к неофициальному методу ContentProvider» https : //stackoverflow.com/a/20559175/690777

6
задан Ethan 27 June 2009 в 06:34
поделиться

9 ответов

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

(financial_document.assets or []).length

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

7
ответ дан 8 December 2019 в 02:46
поделиться

Случай 1:

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

Случай 2:

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

3
ответ дан 8 December 2019 в 02:46
поделиться

Более общий способ решения этого класса проблем - добавить метод try к объекту:

  ##
  #   @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 на объекте.

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

3
ответ дан 8 December 2019 в 02:46
поделиться

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

financial_document.assets.andand.length || 0
3
ответ дан 8 December 2019 в 02:46
поделиться

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

class FinancialDocument

  def assets_length
    assets.length.blank? 0 : assets.length
  end
end
0
ответ дан 8 December 2019 в 02:46
поделиться

Dave W. Smith is on the right track.

Check this out: http://www.nach-vorne.de/2007/4/24/attr_accessor-on-steroids

One easy solution would look something like this:

class FinancialDocument
  attr_accessor :assets
  def assets
    @assets ||= Array.new
  end
  ...
end
8
ответ дан 8 December 2019 в 02:46
поделиться

The less repetitive way of dealing with this is to ensure that financial_document.assets is always a non-null object, by arranging for it to hold an appropriate sentinel value (e.g., an empty collection, or a special object that has degenerate behavior).

See The Null Object Pattern.

7
ответ дан 8 December 2019 в 02:46
поделиться

You can make it a bit shorter:

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

because

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

but in general, IMHO there's no less repetitive way, only various workarounds. (And this is one of the things I don't like so much in Ruby.) You can make sure that objects aren't null (as other people are suggesting here) - but you can't do that everywhere. You can wrap up the nil-checking code in helper methods or in begin-rescue blocks.

For example, rather than adding length method to nil object (which is IMHO a dirty hack), I'd wrote a helper method - a "length getter":

def fd_length(financial_document)
  financial_document.assets ? financial_document.assets.length : '0'
end
0
ответ дан 8 December 2019 в 02:46
поделиться

This being Ruby, you could add a length method to NilClass and have it always return 0.

0
ответ дан 8 December 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: