对作为一个组

时间:2017-02-04 19:19:34

标签: ruby-on-rails ruby ruby-on-rails-4 domain-data-modelling

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

鉴于模型,我们将其称为 PurchaseOrder ,具有以下属性:

  • amount_to_produce
  • amount_taken_from_stock
  • placement_date
  • DELIVERY_DATE
  • PRODUCT_ID
  • 的client_id

作为用户,我希望能够看到这些 PurchaseOrder 的表格列表,并在必要时看到群组

明细信息:当 PurchaseOrder 的集合被分组时,该分组集合的行为应该与 PurchaseOrder 完全相同必须在表中显示为记录,过滤操作应该在分组记录上工作,就像在单个PurchaseOrder实例上一样,对于分页和排序也是如此。此外,必须缓存或者至少我是这样认为的, amount_to_produce amount_taken_from_stock 的总和,最小值< em> 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查找记录,就可以将分组记录排除在表格之外。 / p>

然而,我预见到了直接的弊端:

  1. 更新组成员属性时,例如 amount_to_produce ,父级缓存 amount_to_produce 也应更新,其他三个属性也相同。这可能导致模型回调before_update,我倾向于不使用它,除非它涉及单个实例本身的行为。
  2. 取消组合成员时,同一历史记录
  3. 同样在销毁小组成员时(可能会发生)。
  4. 对于 1。,我们可能暗示不需要在父 PurchaseOrder 中缓存金额或日期属性,因为我们可以覆盖getter for getter那些属性并返回孩子的总和/分钟,如果 purchase_orders.size.nonzero?,然而,这闻起来像是错误的。

    总而言之,我想尽管不是最好的,乐观的方法来模拟这个场景,并且关于将成员分组和取消组合的方法,关于什么是最好的域名的想法实现它,我想到像Groupable这样的问题。

    Pd:对于每个组,该组的client_id将是一个名为&#34; Multiple Customers&#34;的默认种子客户端,以及product_id,与子项的product_id相同,因为它是&#39; sa限制只能将具有相同product_id的 PurchaseOrder 分组,不能将具有不同 product_id 的组分组。

    感谢。

1 个答案:

答案 0 :(得分: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创建一个PurchaseOrderGroup,即使只有一个,也保持相同的接口。然后,您可以在PurchaseOrderGroup上定义委托方法,这些方法可以获取子项的相应总和,最小值,最大值等 - 聚合查询应该对此进行简短的处理。见上面的aggregate_pos()方法。很容易在PurchaseOrderGroup类中缓存此结果。删除或添加PurchaseOrder对象很简单,只需再次调用aggregate_pos()。

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