2013-07-15 3 views
0

У меня есть модель Product, которая имеет много Items. В приложении перечислены уникальные элементы, принадлежащие продукту. Поэтому подумайте о предметах как инвентаре. Следующий запрос захватывает признанные элементы для продукта и удаляет первый элемент (не имеет значения, но он становится признаком, отображаемым отдельно, если вам интересно).Обработка значения nil из метода экземпляра в Rails

# product.rb 
has_many :items_in_stock, -> { Item.in_stock }, class_name: 'Item' 
def featured_items 
    items_in_stock.select("DISTINCT ON (condition) id, items.*") 
    .order(:condition, :price) 
    .sort_by { |item| item[:price] }[1..-1] 
end 

# item.rb 
scope :in_stock, -> { where(status: 'in_stock') } 

Беда в том, когда feaured_items пустуют, метод возвращает ноль, а не объект отношение. Это означает, что я получаю сообщение об ошибке, если я вызываю @product.featured_items.any? на продукт, у которого нет элементов. Если я удалю блок sort_by, я получаю пустой объект отношения.

Есть хороший способ справиться с этим, кроме:

items = items_in_stock.select("DISTINCT ON (condition) id, items.*").order(:condition, :price) 
if items.any? 
    items.sort_by { |item| item[:price] }[1..-1] 
end 

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

+0

_ «Беда в том, когда' feaured_items' пустые»_ Я не вижу' featured_items' в любом месте вашего кода. – Phrogz

+0

@Phrogz извините, я исправил его. – dee

ответ

2

вместо if items.any? вы можете использовать unless items.blank?, если это ноль или пусто, он не будет работать условию

items.blank? проверяет как items.empty? и items.nil?

И, конечно, вы можете использовать его в своих featured_items

items = items_in_stock.select("DISTINCT ON (condition) id, items.*") 
    .order(:condition, :price) 
    .sort_by { |item| item[:price] }[1..-1] 
return Array.new if items.blank? 

Таким образом, вы знаете, что результатом будет массив, независимо от того, что

И the proof, вы можете использовать .blank? на nil объекта, и он работает на nil себя, nil.blank? возвращает true

+0

Вы не можете вызвать '.blank?' На 'nil'. Это приведет к ошибке. – dasnixon

+0

Вы действительно можете сделать 'nil.blank?', И он вернет 'true'. Просто протестируйте его. И для доказательства: http://stackoverflow.com/a/888877/1434075 –

+0

Ах да, вы правы, старые добрые Rails ... – dasnixon

3

Я в замешательстве ... зачем звонить .any? на него тогда с nil рассматривается как false в рубине. Если вы вернетесь, это nil, тогда вы знаете, что у вас нет каких-либо featured_items.

Я побежал в irb, и я думаю, что ваша проблема - [1 ..- 1].

a = [] 
# => [] 
a.sort_by { |w| w.length } 
# => [] 
a.sort_by { |w| w.length }[1..-1] 
# => nil 

Самый простой способ это просто сделать

items = items_in_stock.select("DISTINCT ON (condition) id, items.*") 
    .order(:condition, :price) 
    .sort_by { |item| item[:price] } 
items.any? ? items[1..-1] : items 

Тогда вы на самом деле не делать проверку в других частях кода, если это не необходимо.

+0

Я полагаю, что это правда, но ради последовательности. Обычно ActiveRecord возвращает объект отношения. Вызов 'any?' Сообщает вам, есть ли в массиве какие-либо элементы. – dee

+0

@dee см. Мой отредактированный ответ. – dasnixon

+0

Спасибо. Любые предложения по выщипыванию первого значения из массива, но возврату массива, даже если его пустой? – dee

Смежные вопросы