【发布时间】:2021-08-18 09:54:46
【问题描述】:
众所周知,Rails 使用“包含”和“引用”来解决 N+1 个查询。但是,我今天在测试查询时遇到了一个问题。以下是我的 rails 应用程序中的一些模型。
class Organization < ApplicationRecord
has_many :projects, dependent: :destroy
end
class Project < ApplicationRecord
belongs_to :organization
has_many :routes, dependent: :destroy
end
class Route < ApplicationRecord
belongs_to :project
end
正如我们在这里看到的,我们建立了一个嵌套关系。我的查询如下:
routes = Route.includes(project: :organization).where("organizations.name like ?", "blablabla").references(project: :organization)
这个查询可以按我的预期成功获取路由记录。不过,我也试过:
routes = Route.includes(project: :organization).where("organizations.name like ?", "blablabla").references(:projects)
和
routes = Route.includes(project: :organization).where("organizations.name like ?", "blablabla").references("xxxxxx")
后两个查询都可以工作并获得我想要的路线记录。据我了解,“包含”必须与“参考”一起使用。而“references”表示我们要在查询语句中加入的表。但似乎只要我将一个参数传递给“引用”,无论这个参数是什么,它都可以工作。
从 ActiveRecord 源代码来看,“引用”似乎只检查您是否传递了 table_names。
def references(*table_names)
check_if_method_has_arguments!(:references, table_names)
spawn.references!(*table_names)
end
def references!(*table_names) # :nodoc:
self.references_values |= table_names
self
end
谁能详细说明这个“参考”是如何工作的?
【问题讨论】:
-
什么版本的导轨?
-
在两个查询中包括加载记录 - 第一个从路由表加载所有行,然后在您访问关联时触发第二个。
references告诉 ActiveRecord 您想在第一个查询中引用该表 - 通常是为了过滤行。 -
无论您是否使用
references,查询都有效的原因是 where 子句导致它由触发单个查询的eager_load处理。这篇文章解释得更好然后我可以medium.com/@gandhi.nikita20/… -
这是 Rails 6.0.3.4
-
@max 谢谢 max,我认为这篇文章完美地回答了我的问题。但我想知道,既然“包含”加上“哪里”可以完成这项工作,为什么需要“参考”?
标签: ruby-on-rails activerecord