Steven
Steven

Reputation: 18004

Eager loading an associated record while also joining it in Rails

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

Answers (1)

Milan Novota
Milan Novota

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

Related Questions