我有一个Project
和User
模型,它们通过一个Permission
带有 has_many 多态关联的模型连接。权限表还跟踪挂起状态。相关设置如下:
class Project < ActiveRecord::Base
has_many :permissions, as: :permissionable
has_many :contributors, through: :permissions, source: :user
has_many :pending_contributors, through: :permissions, source: :user, conditions: '"permissions"."accepted" = false'
...
end
class Permission < ActiveRecord::Base
belongs_to :user
belongs_to :permissionable, polymorphic: true
...
end
class User < ActiveRecord::Base
has_many :permissions
has_many :projects, through: :permissions, source: :permissionable, source_type:'Project'
...
end
我正在尝试访问项目中的贡献者和 pending_contributors 列表,而不会在渲染所有项目时导致 N+1 查询问题。问题是我不能使用includes(:contributors, :pending_contributors)
,因为首先提到的两者中的任何一个都是唯一有效的。
例如在我的 Rails 控制台中:
u = User.find(2)
u.projects.includes(:contributors, :pending_contributors).each do
|p| puts p.contributors.map(&:id).inspect
end
在我的 rails 控制台中的结果是:
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 2]]
Project Load (1.3ms) SELECT "projects".* FROM "projects" INNER JOIN "permissions" ON "projects"."id" = "permissions"."permissionable_id" WHERE "permissions"."user_id" = 2 AND "permissions"."permissionable_type" = 'Project'
Permission Load (1.1ms) SELECT "permissions".* FROM "permissions" WHERE "permissions"."permissionable_type" = 'Project' AND "permissions"."permissionable_id" IN (64, 56, 54, 53, 51, 50, 61, 62, 63, 57, 65, 66, 48, 49, 67, 68, 69, 70, 71, 60, 72, 16, 14, 11)
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (2, 18, 20, 41, 40, 3, 17, 34, 37, 39, 43, 19, 22, 42)
前三个结果是:
[2, 18, 20, 2]
[2]
[41, 2, 40, 18]
现在交换包含的顺序如下:
u = User.find(2)
u.projects.includes(:pending_contributors, :contributors).each do
|p| puts p.contributors.map(&:id).inspect
end
结果突然发生了变化(产生了我预期的结果)-注意权限加载行,它现在将 :pending_contributors 条件添加到该查询中:
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 2]]
Project Load (1.1ms) SELECT "projects".* FROM "projects" INNER JOIN "permissions" ON "projects"."id" = "permissions"."permissionable_id" WHERE "permissions"."user_id" = 2 AND "permissions"."permissionable_type" = 'Project'
Permission Load (1.4ms) SELECT "permissions".* FROM "permissions" WHERE "permissions"."permissionable_type" = 'Project' AND "permissions"."permissionable_id" IN (64, 56, 54, 53, 51, 50, 61, 62, 63, 57, 65, 66, 48, 49, 67, 68, 69, 70, 71, 60, 72, 16, 14, 11) AND ("permissions"."accepted" = false)
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (18, 19, 40, 3, 22, 43, 42, 41, 2, 20)
结果是:
[20]
[]
[41, 40, 18]
如果我不是访问pending_contributors,而是访问贡献者,我会反过来遇到同样的问题。我很确定这是因为 pending_contributors 和贡献者都使用相同的来源,但我不确定为什么这是一个问题。
有没有办法呈现所有项目并访问贡献者,以及每个项目的 pending_contributors 而不会导致 N+1 查询?
注意:我在 Rails 3.2 上。