Решение для тех, у кого возникли проблемы после перехода на KitKat:
«Это позволит получить путь к файлу от MediaProvider, DownloadsProvider и ExternalStorageProvider, а также вернуться к неофициальному методу ContentProvider» https : //stackoverflow.com/a/20559175/690777
Лично я бы использовал оператор / ключевое слово или
:
(financial_document.assets or []).length
В любом случае, .length
вызывается в массиве, давая вам 0
, если ноль
.
Случай 1:
financial_document
и активы
имеют много взаимосвязей. В этом случае financial_document.assets
всегда возвращает массив. Таким образом, financial_document.assets.size
даст вам 0
, если соответствующая дочерняя запись не найдена, и размер в противном случае.
Случай 2:
assets
- это просто метод / атрибут в финансовом_документе
.
Затем получите массив, возвращаемый методом assets
, чтобы вы всегда могли вызвать для него .size. Как и указал Джоэл.
Более общий способ решения этого класса проблем - добавить метод 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
В этом случае я использую и gem :
financial_document.assets.andand.length || 0
Что-то в модели, которое возвращает 0 или длину. Это избавляет вас от необходимости делать что-то, что, на ваш взгляд, слишком дорого. Подобные вещи обычно можно сделать в модели.
class FinancialDocument
def assets_length
assets.length.blank? 0 : assets.length
end
end
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
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).
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
This being Ruby, you could add a length method to NilClass and have it always return 0.