我将我的 Product
模型加入到自身 :through
模型 BundleConstituent
。通过这种配置,一个产品(捆绑)可以有很多产品(成分),而这些成分可以有很多捆绑。
产品型号
has_many :bundle_constituents, dependent: :destroy
has_many :constituents, through: :bundle_constituents
has_many :products, through: :bundle_constituents, foreign_key: 'constituent_id'
BundleConstituent 模型
create_table :bundle_constituents do |t|
t.references :product, null: false, foreign_key: true, index: false
t.integer :constituent_qty
t.references :constituent, null: false, foreign_key: {to_table: :products}, index: false
t.index [:product_id, :constituent_id], unique: true
t.timestamps
end
我能够在 BundleConstituent
模型中轻松创建记录,并且可以毫无问题地使用 Product.find(2).constituents
查询包。 问题发生在我尝试使用 Product.find(8).products
获取属于一个成员的包时,结果查询在 product_id = 8
中查找带有 BundleConstituent
的连接记录,而不是constituent_id=8
。有关控制台的完整输出,请参见下文:
2.6.6 :015 > c.products
Product Load (0.8ms) SELECT `products`.* FROM `products` INNER JOIN `bundle_constituents` ON `products`.`id` = `bundle_constituents`.`product_id` WHERE `bundle_constituents`.`product_id` = 8 LIMIT 11
=> #<ActiveRecord::Associations::CollectionProxy []>
我认为在 Product 模型中的 :foreign_key
上指定 has_many :products
会解决这个问题,但似乎没有。如何强制查询引用 constituent_id
列而不是 product_id
列?
编辑:(来自我下面的评论)
我使用范围创建了一个解决方法来实现我的目标:
scope :respective_bundles, -> (const_id){ includes(:bundle_constituents).all.select{|i| i.bundle_constituents.present?}.select{|i| i.bundle_constituents.select{|j| j.constituent_id == const_id}}}
其中 const_id
是相关组成产品的 ID 的 ID。尽管如此,这似乎是一种黑客行为,我会对更优雅的东西感兴趣,而无需构建如此繁琐的查询。