聚合has_many返回的属性的值

时间:2016-03-15 15:16:14

标签: ruby-on-rails ruby activerecord

数据结构如下:

class Job 
  has_many job_sections 
  has_many job_products, through job_sections 
end

class JobSection 
  belongs_to job
  has_many job_products 
end

class JobProduct 
  belongs_to product
  belongs_to job_section 
end

当我打电话给job.job_products时,我最终可能会遇到这样的事情:

 #<JobProduct:0x007ff4128b0ca0
  id: 18133,
  product_id: 250,
  quantity: 3,
  frozen_cache: {},
  discount: 0.0,
 #<JobProduct:0x007ff4128b00c0
  id: 18134,
  product_id: 250,
  quantity: 1,
  frozen_cache: {},
  discount: 0.0]

正如您所看到的,product_id在两个实例中都是相同的。 如何按产品ID合并数组的内容,以便检索并作为聚合值对其进行操作?

在某种程度上,我需要能够通过product_id而不是id对作业产品采取行动。

有效的结果是这样......

 [#<SomeFancySeerviceObjectMaybe?
  product_id: 250,
  quantity: 4,
  frozen_cache: {},
  discount: 0.0]

我是否选择了一个简单的旧Ruby对象来处理它们,或者我是否必须重新考虑它的架构,或者是否(希望!)有一些Rails秘密酱可以帮助我吗? / p>

* FYI Job Section是该架构的最新成员,我不认为它经过特别深思熟虑。但是,我不能花太多时间来扭转现有的情况。 这个设置并不理想,我可能是多年来开始挑选它的第六个开发者。

非常欢迎您的建议。谢谢

1 个答案:

答案 0 :(得分:1)

在SQL中,这将是这样的:

SELECT SUM(quantity)
FROM   job_products
WHERE  product_id = 250
GROUP BY product_id

您也可以在ActiveRecord中执行此操作。如果您只想要一个整数,可以使用pluck

total_quantity = job.job_products.
  group(:product_id).
  pluck("SUM(job_products.quantity)").
  first

如果需要,您还可以pluck多个列(在Rails 4+中),这就是它返回数组的原因。因此,如果您想同时享受平均折扣,那就很容易了。

如果您更喜欢JobProduct实例,也可以获得该实例,但在您的情况下,由于分组,很多属性将为nil。但你可以说:

summary = job.job_products.
  group(:product_id).
  select("SUM(job_products.quantity) AS total_quantity").
  first

您将获得一个只读JobProduct,其中包含名为total_quantity的额外属性。所以你可以做summary.total_quantity。但由于分组,summary会有nil iddiscount等。基本上它只会有与select相匹配的属性。这有点奇怪,但有时候它会让你编写适用于&#34;真实&#34; JobProduct和这些摘要版本。