我有一个实体Order
,它由两个子实体SalesOrder
和PurchaseOrder
组成。这两个子实体共享其行为的95%。
单表继承和代码如何最好地接近这个或者有更好的方法吗?
class Order < ActiveRecord::Base
belongs_to :order_type
end
class SalesOrder < Order
before_validation(on: :create) do
self.order_type = OrderType.find_by!(name: "Sales order")
end
validates_inclusion_of :order_type_id, in: [OrderType.find_by!(name: 'Sales order').id]
validate :potential_savings, numericality: true, allow_nil: true
default_scope { joins(:order_type).where("order_types.name = ?", "Sales order") }
# OrderItem also has two sub entities (SalesOrderItem and PurchaseOrderItem with slightly different behaviour)
has_many :order_items, class_name: "SalesOrderItem", foreign_key: "order_id", inverse_of: :order
end
class PurchaseOrder < Order
before_validation(on: :create) do
self.order_type = OrderType.find_by!(name: "Purchase order")
end
validates_inclusion_of :order_type_id, :in => [OrderType.find_by!(name: 'Purchase order').id]
validates_inclusion_of :potential_savings, :in => [nil], allow_nil: true # throw error if not nil
default_scope { joins(:order_type).where("order_types.name = ?", "Purchase order") }
# OrderItem also has two sub entities (SalesOrderItem and PurchaseOrderItem with slightly different behaviour)
has_many :order_items, class_name: "PurchaseOrderItem", foreign_key: "order_id", inverse_of: :order
end
答案 0 :(得分:1)
我不知道您的数据模型的所有细节,但也许您可以将共享功能放入Concern
。
类似的东西:
module Orderable
extend ActiveSupport::Concern
included do
cattr_reader :order_type
# All common/shared relations and validations are defined here
belongs_to :order_type
before_validation(on: :create) do
self.order_type = OrderType.find_by!(name: @@order_type)
end
validates_inclusion_of :order_type_id, in: [OrderType.find_by!(name: @@order_type).id]
default_scope { joins(:order_type).where("order_types.name = ?", @@order_type) }
end
module ClassMethods
def set_order_type(order_type)
self.class_variable_set("@@order_type", order_type)
end
end
end
class SalesOrder < ActiveRecord::Base
# Include the concern and call a method on the concern to set the order_type
include Orderable
set_order_type 'Sales order'
# This validation is too different from the corresponding PurchaseOrder validation
# so it is put in the model and not in the Orderable concern
validate :potential_savings, numericality: true, allow_nil: true
end
class PurchaseOrder < ActiveRecord::Base
include Orderable
set_order_type 'Purchase order'
# This validation is too different from the corresponding PurchaseOrder validation
# so it is put in the model and not in the Orderable concern
validates_inclusion_of :potential_savings, :in => [nil], allow_nil: true # throw error if not nil
end
不确定这是否更强大或DRY然后采用STI方式。此外,由于order_type名称的格式不同,最后的验证尚未实现,但可以修复。
我希望这会有所帮助或给予一些启发。
答案 1 :(得分:1)
SalesOrder 是订单。所以,我认为继承是最好的方法。如果两种类型具有相同或几乎相同的数据,则STI是最佳策略。如果您觉得这种方法会创建很多空列,我会建议尝试不同的策略,但保留继承。