如何在Rails ActiveRecord中获取实体下的多态关联Position
获取Entity下所有Positions的解决方案
问题分析
你的Entity模型关联了Invoice和Offer,这两个模型都是Position的多态关联对象。要获取某个Entity的所有Positions,需要通过关联的Invoice和Offer间接查询,你之前的方法错误在于没有利用已有的关联关系构建正确的查询逻辑。
可行方法
方法1:在Entity模型中添加自定义查询方法
直接在Entity里定义方法,通过SQL条件匹配关联的Invoice和Offer对应的Positions:
class Entity < ApplicationRecord has_many :invoices, dependent: :restrict_with_error has_many :offers, dependent: :restrict_with_error # 获取当前实体的所有positions def positions Position.where( "(positionable_type = 'Invoice' AND positionable_id IN (?)) OR (positionable_type = 'Offer' AND positionable_id IN (?))", invoice_ids, offer_ids ) end end
使用方式:
@entity = Entity.first @all_positions = @entity.positions
方法2:通过关联对象分别查询后合并
利用Active Record的or方法合并两个查询结果:
@entity = Entity.first invoice_positions = Position.where(positionable: @entity.invoices) offer_positions = Position.where(positionable: @entity.offers) @all_positions = invoice_positions.or(offer_positions)
方法3:通过has_many :through关联后合并
先在Entity中定义到Invoice和Offer的Positions的间接关联,再合并结果:
class Entity < ApplicationRecord has_many :invoices, dependent: :restrict_with_error has_many :offers, dependent: :restrict_with_error has_many :invoice_positions, through: :invoices, source: :positions has_many :offer_positions, through: :offers, source: :positions def positions invoice_positions.or(offer_positions) end end
使用方式和方法1一致,直接调用@entity.positions即可。
你之前方法的错误原因
@entity.positionables.positions:你的Entity模型未定义positionables关联,且即使定义,也无法直接通过该关联调用positions方法。Position.preload(:positionable).positions:Position.preload(:positionable)返回的是ActiveRecord::Relation集合对象,该对象没有positions方法,你需要的是查询关联到目标Entity的Positionable对象的Position记录。
内容的提问来源于stack exchange,提问作者Ricky883249
相关产品推荐
相关产品推荐

