You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:20:08