对充当组的记录集合进行建模

Modelling a collection of records that act as as a group

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

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

作为用户,我希望能够看到这些 PurchaseOrder 的 table 列表,并且在必要时,group 他们。

详细信息:当 PurchaseOrder 的集合被分组时,该分组集合的行为应该与 PurchaseOrder 完全相同,从某种意义上说,它必须显示为 table 中的一条记录,过滤操作应该像在单个 PurchaseOrder 实例上那样对分组记录进行过滤操作,分页和排序也是如此。此外,必须缓存或者至少我是这么想的,amount_to_produce、[=33=的总和]amount_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

这样就可以轻松实现在table视图中显示的目的,过滤分页和排序就可以开箱即用,只需将记录范围设为group_id nil,分组table.

中可以省略记录

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

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

对于 1. 我们可以暗示没有必要在 parent PurchaseOrder 中缓存金额或日期属性,因为我们可以覆盖这些属性的 getter 和 return children 的总和/分钟 if purchase_orders.size.nonzero?,但是,这闻起来有点不对劲。

所以总结一下,如果不是最好的话,我想要一种乐观的方法来模拟这种情况,以及关于将成员分组和取消分组的方法,关于什么是实施它的最佳领域的想法,我正在考虑像 Groupable 这样的问题。

Pd:对于每个组,组的client_id将是一个名为"Multiple Customers"的默认种子客户端,而product_id与product_id相同children 的限制,因为只有具有相同 product_id 的 PurchaseOrder 可以分组,所以不能对具有不同 product_id 的组进行分组的可以分组

谢谢。

我会把它分成两个模型,一个 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 创建一个 PurchaseOrderGroup,即使只有一个,它保持相同的界面。然后,您可以在 PurchaseOrderGroup 上定义委托方法,以获取子项的适当总和、最小值、最大值等 - 聚合查询应该可以缩短工作时间。参见上面的 aggregate_pos() 方法。很容易将此结果缓存在 PurchaseOrderGroup class 中。删除或添加 PurchaseOrder 对象很容易,只需再次调用 aggregate_pos() 即可。

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