简体   繁体   English

Rails:一次为 has_many 和 has_many 获取记录:通过关联

[英]Rails: fetch records at once for has_many and has_many :through associations

Given the following models:鉴于以下模型:

User用户

class User < ActiveRecord::Base
  has_many :given_loans,    :class_name => "Loan", :foreign_key => "lender_id"
  has_many :received_loans, :class_name => "Loan", :foreign_key => "borrower_id"
  has_many :borrowed_books, :class_name => "Book", :foreign_key => "borrower_id", :through => :received_loans
  has_many :own_books,      :class_name => "Book", :foreign_key => "owner_id"
end

Book

class Book < ActiveRecord::Base
  belongs_to :owner,     :class_name => "User", :foreign_key => "owner_id"
  has_many   :loans,     :foreign_key => "borrowed_book_id"
  has_many   :borrowers, :through => "loans",   :foreign_key => "borrowed_book_id"
end

Loan贷款

class Loan < ActiveRecord::Base
  belongs_to :borrowed_book, :class_name => "Book", :foreign_key => "borrowed_book_id"
  belongs_to :borrower,      :class_name => "User", :foreign_key => "borrower_id"
  belongs_to :lender,        :class_name => "User", :foreign_key => "lender_id"
end

These relationships seem to work fine.这些关系似乎运作良好。

Now I'd like to query all books for a user, including both the borrowed books and the owned books, which I'm currently doing like this:现在我想查询用户的所有书籍,包括借来的书籍和拥有的书籍,我目前正在这样做:

def books
  own_books + borrowed_books
end

This method naturally causes two SQL queries, though:但是,此方法自然会导致两个 SQL 查询:

Book Load (0.4ms)  SELECT "books".* FROM "books" WHERE ("books".owner_id = 1)
Book Load (0.3ms)  SELECT "books".* FROM "books" INNER JOIN "loans" ON "books".id = "loans".borrowed_book_id WHERE (("loans".borrower_id = 1))

Furthermore I'm not able to run active record methods such as limit or order against this selection, which would be nice to have.此外,我无法针对此选择运行活动记录方法,例如limit或订单,这会很好。 After all I'm fetching the books from the same table.毕竟我是从同一张桌子上取书。

I'm assuming that there's a better (more "Rails'") and more efficient way of doing this.我假设有一种更好(更多“Rails”)和更有效的方法来做到这一点。 Anyone care to point me into the right direction ?有人愿意指出我正确的方向吗? Cheers!干杯!


PS: A possible solution that came to mind was to define a query for a has_many :books relationship, but that didn't seem quite right either. PS:想到的一个可能的解决方案是为has_many :books关系定义一个查询,但这似乎也不完全正确。

Here's what I ended up doing.这就是我最终做的。

Using the meta_where gem the following method is possible to improve the situation:使用meta_where gem 可以通过以下方法来改善这种情况:

def books
  Book.includes(:loans).where({ "owner_id" => self.id } | { "loans.borrower_id" => self.id })
end

This method returns a relation object and produces only one SQL query.此方法返回一个关系对象并仅生成一个 SQL 查询。 Any opinions where this method should be located?这个方法应该放在什么地方有什么意见吗? Right now I'm having it in the User class.现在我在User类中使用它。

Use this in the model:在模型中使用它:

def as_json(options={})
super(include: { trades: { include:  :trades } })
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM