简体   繁体   中英

Rails “includes” Method and Avoiding N+1 Query

I don't understand the Rails includes method as well as I'd like, and I ran into an issue that I'm hoping to clarify. I have a Board model that has_many :members and has_many :lists (and a list has_many :cards ). In the following boards controller , the show method looks as follows:

def show
  @board = Board.includes(:members, lists: :cards).find(params[:id])
  ...
end

Why is the includes method needed here? Why couldn't we just use @board = Board.find(params[:id]) and then access the members and lists via @board.members and @board.lists ? I guess I'm not really seeing why we would need to prefetch. It'd be awesome if someone could detail why this is more effective in terms of SQL queries. Thanks!

Per the Rails docs:

Eager loading is the mechanism for loading the associated records of the objects returned by Model.find using as few queries as possible.

When you simply load a record and later query its different relationships, you have to run a query each time. Take this example, also from the Rails docs:

clients = Client.limit(10)

clients.each do |client|
  puts client.address.postcode
end

This code executes a database call 11 times to do something pretty trivial, because it has to do each lookup, one at a time.

Compare the above code to this example:

clients = Client.includes(:address).limit(10)

clients.each do |client|
  puts client.address.postcode
end 

This code executes a database call 2 times, because all of the necessary associations are included at the onset.

Here's a link to the pertinent section of the Rails docs.

Extra

A point to note as of recent: if you do a more complex query with an associated model like so:

Board.includes(:members, lists: :cards).where('members.color = ?', 'foo').references(:members)

You need to make sure to include the appended references(:used_eager_loaded_class) to complete the query.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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