Reputation: 18004
Let's say I have books, each belonging to an author. I'd like to print out a list of books as well as some associated author information. I would, as an initial pass, simply use
@books = Book.all
In my controller and
book.author.name
In my view, resulting in @books.count
separate queries (the "n+1" problem). The solution as recommended is
@books = Books.includes(:author)
Which reduces it to a constant number of queries.
Now if I needed to filter the book list based on some criteria having to do with the author, I would do in the controller
@books = Books.joins(:author).where('name like "%Richler%"')
But this reintroduces the "n+1" problem. If I try to fit in .includes(:author)
in the query, it tries to pull it in twice, and name
becomes ambiguous. In regular MySQL, I would just use something like:
SELECT * FROM books LEFT OUTER JOIN authors ON books.author_id = authors.id
WHERE authors.name LIKE "%Richler%";
or
SELECT * FROM books, authors WHERE
authors.name LIKE "%Richler%" AND books.author_id = authors.id;
But short of writing just a SQL query string, what's the Railsish way to accomplish this?
Upvotes: 0
Views: 702
Reputation: 15596
This should do the job:
Book.joins(:author).where('authors.name like "%Richler%"').includes(:author)
This should fire just two SQL queries.
Upvotes: 4