Rails双向自引用表实现替代产品一次创建双向生效如何配置?
现有代码的核心问题是has_many :alternatives, through: :product_alternatives无法自动识别需要从Alternative模型中取product_one还是product_two作为关联目标,需要拆分双向关联后合并结果,调整方案如下:
调整后的Product模型代码
class Product < ApplicationRecord # 作为product_one端的替代关联,取关联的product_two作为替代产品 has_many :relation_as_one, class_name: 'Alternative', foreign_key: 'product_one_id' has_many :alternatives_from_one, through: :relation_as_one, source: :product_two # 作为product_two端的替代关联,取关联的product_one作为替代产品 has_many :relation_as_two, class_name: 'Alternative', foreign_key: 'product_two_id' has_many :alternatives_from_two, through: :relation_as_two, source: :product_one # 合并两个方向的替代产品,返回支持链式调用的ActiveRecord关系对象 def alternatives alternatives_from_one.or(alternatives_from_two) end end
可选优化:新增关联唯一性校验
避免重复创建A-B和B-A两条重复的替代关系,在Alternative模型中增加校验规则:
class Alternative < ApplicationRecord belongs_to :product_one, class_name: 'Product' belongs_to :product_two, class_name: 'Product' # 避免同方向重复创建 validates :product_one_id, uniqueness: { scope: :product_two_id } # 避免反方向重复创建 validate :check_reverse_uniqueness private def check_reverse_uniqueness if Alternative.exists?(product_one_id: product_two_id, product_two_id: product_one_id) errors.add(:base, "两个产品的替代关系已存在") end end end
调整后执行Alternative.create(product_one: productA, product_two: productB),即可实现productA.alternatives返回[productB],productB.alternatives返回[productA]的预期效果。
内容的提问来源于stack exchange,提问作者bmaw
相关产品推荐
相关产品推荐

