动态 has_many class_name 使用多态引用

Dynamic has_many class_name using polymorphic reference

我正在尝试将多态模型(在本例中为 Product)关联到基于 class 的动态名称(StoreOnePurchaseStoreTwoPurchase) =17=] products table.

上的多态引用列
class Product < ActiveRecord::Base
  belongs_to :store, polymorphic: true
  has_many :purchases, class_name: (StoreOnePurchase|StoreTwoPurchase)
end

class StoreOne < ActiveRecord::Base
  has_many :products, as: :store
  has_many :purchases, through: :products
end

class StoreOnePurchase < ActiveRecord::Base
  belongs_to :product
end

class StoreTwo < ActiveRecord::Base
  has_many :products, as: :store
  has_many :purchases, through: :products
end

class StoreTwoPurchase < ActiveRecord::Base
  belongs_to :product
end

StoreOnePurchaseStoreTwoPurchase 必须是不同的模型,因为它们包含非常不同的 table 结构,StoreOneStoreTwo.[=23 也是如此=]

我知道引入 HABTM 关系可以像这样解决这个问题:

class ProductPurchase < ActiveRecord::Base
  belongs_to :product
  belongs_to :purchase, polymorphic: true
end

class Product < ActiveRecord::Base
  belongs_to :store, polymorphic: true
  has_many :product_purchases
end

class StoreOnePurchase < ActiveRecord::Base
  has_one :product_purchase, as: :purchase
  delegate :product, to: :product_purchase
end

但是我有兴趣看看是否可以不用额外的 table?

非常有趣的问题。但是,不幸的是,没有额外的 table 是不可能的,因为没有多态的 has_many 关联。 Rails 将无法像 Product.store (belongs_to) 那样动态地确定 Product.purchases (has_many) 的类型。因为 Product 中没有 purchases_type 列,并且 has_many 中不支持任何动态解析的关联类型。你可以像下面这样做一些技巧:

class Product < ActiveRecord::Base
  class DynamicStoreClass
     def to_s
        #return 'StoreOnePurchase' or 'StoreTwoPurchase'
     end
  end      
  belongs_to :store, polymorphic: true
  has_many :purchases, class_name: DynamicStoreClass
end

它不会抛出错误,但它是无用的,因为它只会在实例化产品之前调用 DynamicStoreClass.to_s 一次。

您也可以覆盖 ActiveRecord::Associations::association 以支持 class 中的多态类型,但它正在重新发明 Rails。

我宁愿更改数据库架构。