1

我正在为 Ruby-Like(Rails 4/5)中的具体或抽象方法寻找方向,以模拟以下需求或用户故事:

给定一个模型,我们称它为PurchaseOrder并具有以下属性:

  • 生产量
  • amount_taken_from_stock
  • 安置日期
  • 邮寄日期
  • product_id
  • client_id

作为用户,我希望能够看到这些PurchaseOrder的表格列表,并在必要时对它们进行分组

详细信息:当对PurchaseOrder的集合进行分组时,该分组集合的行为应该与PurchaseOrder完全相同,因为它必须在表中显示为记录,过滤操作应该像对单个 PurchaseOrder 所做的那样对分组记录起作用实例,分页和排序也是如此。此外,该必须缓存或者至少我是这样认为的,amount_to_produceamount_taken_from_stock的总和,所有放置日期中的最小placement_date以及最后但并非最不重要的,它们中的最小delivery_date的总和。

我在想像这样在PurchaseOrder中隐式地建模:

Class PurchaseOrder < ApplicationRecord

    belongs_to :group, class_name: PurchaseOrder.model_name.to_s, inverse_of: :purchase_orders

    # purchase order can represent a "group" of purchase orders
    has_many :purchase_orders, inverse_of: :group, foreign_key: :group_id
 end

这样就可以轻松实现在表视图中显示的目的,过滤分页和排序将开箱即用,只需使用 group_id nil 限定记录范围,就可以将分组记录排除在表之外。

但是我预见到了直接的缺点:

  1. 更新组成员属性时,例如amount_to_produce,父缓存的amount_to_produce也应该更新,其他三个属性相同。这可能会导致模型回调 before_update,除非它涉及单个实例本身的行为,否则我倾向于不使用它。
  2. 取消分组成员时,相同的历史记录
  3. 销毁组成员时也是如此(它可以并且将会发生)。

对于1.我们可以暗示不需要在父PurchaseOrder中缓存金额或日期属性,因为我们可以覆盖这些属性的 getter 并在purchase_orders.size.nonzero 时返回子项的总和/分钟?,但是,这闻起来有点不对劲。

所以总结一下,如果不是最好的,我想要一种乐观的方法来模拟这种情况,以及关于将成员分组和取消分组到组/从组中的方法,关于实现它的最佳域位置的想法,我在想像 Groupable 这样的问题。

pd:对于每个组,该组的client_id将是一个默认的种子客户端,称为“多个客户”,而product_id与孩子的product_id相同,因为限制只能对具有相同product_id的PurchaseOrder进行分组,不能对具有不同product_id 的组进行分组。

谢谢。

4

1 回答 1

1

我会将其拆分为两个模型,一个 PurchaseOrderGroup 和一个 PurchaseOrder。

class PurchaseOrderGroup < ApplicationRecord
  has_many :purchase_orders
  belongs_to :product

  def aggregate_pos
    PurchaseOrder.where(purchase_order_group_id: self.id).
      group(:purchase_order_group_id).
      pluck('sum(amount_to_produce), min(delivery_date), ...')
  end
end

class PurchaseOrder < ApplicationRecord
  belongs_to :purchase_order_group
end

即使只有一个 PurchaseOrder,我也会为每个 PurchaseOrder 创建一个 PurchaseOrderGroup,它维护相同的接口。然后,您可以在 PurchaseOrderGroup 上定义委托方法,这些方法可以获取子项的适当总和、最小值、最大值等 - 聚合查询应该可以轻松完成。见上面的 aggregate_pos() 方法。很容易在 PurchaseOrderGroup 类中缓存这个结果。删除或添加 PurchaseOrder 对象很容易,只需再次调用 aggregate_pos() 即可。

这也消除了 product_id 的困境,只需将该属性放在组上而不是 PurchaseOrder 上。这样,同一组中的两个 PurchaseOrder 不可能有不同的 product_id。

于 2017-02-05T07:36:37.767 回答