0

在我的应用程序中,主要对象是 Accounts 和 Phones,具有典型的 has_many :through Contacts,例如:

Account:
has_many :contacts
has_many :phones, :though => contacts

Phone:
has_many :contacts
has_many :accounts, :though => :contacts

Contact:
belongs_to :account
belongs_to :phone

联系人有字段 signup_status, name 每个唯一的帐户/电话对有一个联系人

对于 id = 123 的帐户,它有 5 个联系人,每个联系人都有一部电话,是否有一个查询会产生所有 5 行并包括所有帐户字段和联系人字段和电话字段?

4

2 回答 2

2

您可以使用预先加载的关联在一个活动记录查询中获取您需要的所有数据

@account = Account.includes(:contacts, :phones).find(123)

,这实际上将转换为三个 SQL 查询:

SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1  [["id", 123]]
SELECT "contacts".* FROM "contacts" WHERE "contacts"."account_id" IN (123)
SELECT "phones".* FROM "phones" WHERE "phones"."id" IN (<phone ids found in prev query>)

所有记录都将加载到内存中,并通过@account 变得可用。要获取联系人和电话数组,只需分别调用@account.contacts@account.phones。请注意,这些调用不会导致重新发出 SQL 查询,这是急切加载的美妙之处。

于 2012-09-26T05:15:48.247 回答
1

ActiveRecord 还不够聪明,无法通过一个 SQL 查询来完成所有这些工作。但是,您可以通过使用包含来非常接近,这将避免 n+1 查询。

Account.includes(:contacts => :phones).where(:id => 123)

ActiveRecord 将执行一次查询以加载所有帐户记录,一次查询以加载所有联系人,一次查询以加载所有电话。有关这背后的原因,请参阅下面的文档链接。

如果您真的想在一个 SQL 查询中获取所有内容(可能有缺点),您应该查看ActiveRecord::Associations::Preloader (文档)

于 2012-09-26T05:12:04.360 回答