Rails try()方法与活动查询中的约束

时间:2013-01-14 00:46:39

标签: ruby-on-rails ruby

我有以下型号:

供应商有许多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()?

4 个答案:

答案 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