Rails如何查询嵌套关联并返回所有嵌套关联

时间:2018-10-26 03:49:42

标签: ruby-on-rails ruby activerecord

我有以下关联:

class User < ApplicationRecord
  has_many :orders
end

class Order < ApplicationRecord
  belongs_to :user
  has_one :invoice
end

class Invoice < ApplicationRecord
  belongs_to :order
  has_one :receipt
end

class Receipt < ApplicationRecord
  belongs_to :invoice
end

我想退还用户拥有的所有订单的所有收据。

如果这种关系在整个过程中都是一对一的,那将很简单:

user = User.find(...)

user.order.invoice.receipt

由于有很多订单,我发现自己想要映射和展平。我不想那样做。我似乎找不到能帮助我真正理解这一概念的资源。我需要定义一个through关系吗?我需要使用.joins吗?

如何退回特定用户拥有的所有订单的发票收据?

2 个答案:

答案 0 :(得分:2)

这应该对您有用:

Receipt.joins(invoice: { order: :user }).where(users: { id: user_id })

是的,您需要使用联接来生成正确的查询(在此过程中联接所有表并添加用户限制)。

答案 1 :(得分:1)

另一个选择是使用子查询。

users = User.where(id: user_id)
orders = Order.where(user_id: users)
invoices = Invoice.where(order_id: orders)
receipts = Receipt.where(invoice_id: invoices)

在加载receipts时,以上代码应执行一个查询。复制到终端后缀时,请在行后加上;nil以防止 inspect 方法(用于显示终端返回值)加载集合。


注意:通常,您需要指定要选择的属性。但是,通过不选择属性来隐式选择 id 属性(主键)。

orders = Order.where(user_id: users)
# is the same as
orders = Order.where(user_id: users.select(:id))

当您需要基于除 id 之外的另一个属性创建子查询时,请记住这一点。例如,当更改子查询方向时。

users = User.where(id: orders.select(:user_id))