如何通过Rails关联查询获取主订单为活跃状态的子订单?
问题描述
我设计了Purchase模型的自关联结构,代码如下:
class Purchase < ApplicationRecord has_one :sub_purchase, class_name: 'Purchase', dependent: :destroy belongs_to :main_purchase, class_name: 'Purchase', foreign_key: 'purchase_id', optional: true end
Purchase模型拥有status属性,其值可能为'active'。我希望查询所有主订单状态为'active'的子订单。
我尝试过如下查询语句,但未达到预期效果:
Purchase.where.not(purchase_id:nil).where(main_purchase: {status: 'active'})
另外我知道可以通过SQL联表查询实现,语句如下:
SELECT * FROM purchases p1 INNER JOIN purchases p2 ON p2.id = p1.purchase_id WHERE p2.status='active';
但我希望尽量避免直接编写SQL,寻求基于Rails ORM的实现方案。
解决方案
你可以通过Rails的joins方法结合已定义的关联来实现,无需编写原生SQL:
Purchase.joins(:main_purchase).where(main_purchase: { status: 'active' })
细节说明
joins(:main_purchase):会自动生成INNER JOIN语句,利用你在belongs_to中定义的关联规则完成自联,同时自动过滤掉没有主订单的记录,所以无需额外写where.not(purchase_id: nil)。where(main_purchase: { status: 'active' }):通过关联名称嵌套条件,Rails会自动处理表别名和字段映射,生成符合需求的WHERE子句。
如果需要更高的代码复用性,还可以结合模型scope实现:
# 在Purchase模型中添加scope scope :active, -> { where(status: 'active') } # 查询时复用该scope Purchase.joins(:main_purchase).merge(Purchase.active)
这种写法可读性更强,后续如果调整active状态的判断逻辑,只需修改scope即可。
内容的提问来源于stack exchange,提问作者Dan SimBed
相关产品推荐
相关产品推荐

