我有以下型号:
供应商有许多submitted_prices
Submitted_prices有很多price_items
为了使代码在没有submission_prices和/或没有price_items时不崩溃,我曾经使用以下内容:
if supplier.submitted_prices.where(:purchaser_id => organization.id).last
&& supplier.submitted_prices.where(:purchaser_id => organization.id).last.price_items.where("item_id" => item.id).last
&& supplier.submitted_prices.where(:purchaser_id => organization.id).last.price_items.where("item_id" => item.id).last.unit_price.present?
order_item.unit_price = supplier.submitted_prices.where(:purchaser_id => organization.id).last.price_items.where("item_id" => item.id).last.unit_price
然后我遇到了try():
order_item.unit_price = supplier.try(:submitted_prices).where(:purchaser_id => organization.id).try(:last).try(:price_items).where("item_id" => item.id).try(:last).try(:unit_price)
问题是,我不知道如何在WHERE约束上运行try(),如果try返回nil,则此约束失败:
NoMethodError Exception: undefined method `where' for nil:NilClass
有没有办法围绕WHERE约束包装try()?
答案 0 :(得分:6)
首先,不要使用try
,恕我直言,这是一种代码气味。
如果您仍然想要,那么您需要在第一次尝试后的每次通话中使用它。
supplier.try(:submitted_prices).try(:where, {purchaser_id: organization.id}).try(:last).try(:price_items).try(:where, {item_id: item.id}).try(:last).try(:unit_price)
这肯定会显示出一些糟糕的设计。尝试先重构它!
答案 1 :(得分:3)
try
接受参数作为其后续参数,例如:
try(:where, :purchaser_id => organization.id)
我建议你将大量的逻辑提取到单独的范围和方法中,在一个if
语句中发生了太多的事情,并且它在对象图中的深度太深。您可能希望了解Law of Demeter/Principle of Least Knowledge。
答案 2 :(得分:3)
这可以在没有try
的情况下完成,并且可以采用更合理,易懂的格式。
submitted_price = supplier.submitted_prices.where(purchaser_id: organization.id).order("created_at desc").first
price_item = submitted_price.price_items.where(item_id: item.id).order("created_at desc").first if submitted_price.present?
order_item.unit_price = price_item.unit_price if price_item.present?
这假设模型按其:created
属性的默认排序。
答案 3 :(得分:1)
我相信你可以通过阅读文档来摆脱这种复杂性 (另外,如果你在不同的行中打破了一系列布尔条款,那将会很棒。我真的很难理解你在那里想做什么)
您应该查看方法association.empty?
和association.exists?(conditions)
。 link