Rails"包括"方法和避免N + 1查询

时间:2015-06-30 22:49:57

标签: ruby-on-rails ruby-on-rails-3

我不理解Rails includes方法以及我喜欢的方法,我遇到了一个我希望澄清的问题。我有一个{strong> Board 模型has_many :membershas_many :lists(以及列表has_many :cards)。在以下板控制器中,show方法如下所示:

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

为什么需要includes方法?为什么我们不能使用@board = Board.find(params[:id]),然后通过@board.members@board.lists访问成员和列表?我想我并没有真正理解为什么我们需要预取。如果有人可以详细说明为什么这在SQL查询方面更有效,那就太棒了。谢谢!

1 个答案:

答案 0 :(得分:3)

根据Rails文档:

  

预先加载是加载相关记录的机制   Model.find使用尽可能少的查询返回的对象。

当您只是加载记录并稍后查询其不同的关系时,您每次都必须运行查询。举个例子,也来自Rails文档:

clients = Client.limit(10)

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

此代码执行11次数据库调用以执行非常简单的操作,因为它必须每次执行一次查找。

将上述代码与此示例进行比较:

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

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

此代码执行数据库调用2次,因为所有必要的关联都包含在开头。

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

<强>附加

最近需要注意的一点:如果您使用相关模型执行更复杂的查询,请执行以下操作:

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

您需要确保包含附加的references(:used_eager_loaded_class)以完成查询。

相关问题