我有以下关联:
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
吗?
如何退回特定用户拥有的所有订单的发票收据?
答案 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))