project
有legacy_users
和group_users
。 group_users
必须通过groups
才能获得users
。我想构建一个project.users
,将这些查询组合为一个arel。
以下是Project
:
class Project < ActiveRecord::Base
has_many :project_accesses
has_many :groups, through: :project_accesses, source: :group
has_many :legacy_users, through: :project_accesses, source: :user
has_many :group_users, through: :groups, source: :users
end
这是Project.find(1).legacy_users
的SQL:
SELECT "users".* FROM "users" INNER JOIN "project_accesses" ON "users"."id" =
"project_accesses"."user_id" WHERE "users"."deleted_at" IS NULL AND
"project_accesses"."deleted_at" IS NULL AND "project_accesses"."project_id" = 1
这是Project.find(1).group_users
的SQL:
SELECT "users".* FROM "users" INNER JOIN "group_memberships" ON "users"."id" =
"group_memberships"."user_id" INNER JOIN "groups" ON "group_memberships"."group_id" =
"groups"."id" INNER JOIN "project_accesses" ON "groups"."id" =
"project_accesses"."group_id" WHERE "users"."deleted_at" IS NULL AND
"group_memberships"."deleted_at" IS NULL AND "groups"."deleted_at" IS NULL AND
"project_accesses"."deleted_at" IS NULL AND "project_accesses"."project_id" = 1
只需在OR
条件下添加INNER JOIN "project_accesses"
即可获得我想要的内容。 Project.find(1).users
:
SELECT "users".* FROM "users" INNER JOIN "group_memberships" ON "users"."id" =
"group_memberships"."user_id" INNER JOIN "groups" ON "group_memberships"."group_id" =
"groups"."id" INNER JOIN "project_accesses" ON ("groups"."id" =
"project_accesses"."group_id" OR "users"."id" = "project_accesses"."user_id") WHERE
"users"."deleted_at" IS NULL AND "group_memberships"."deleted_at" IS NULL AND
"groups"."deleted_at" IS NULL AND "project_accesses"."deleted_at" IS NULL AND
"project_accesses"."project_id" = 1
基本上我只是改为让查询做我想做的事:
INNER JOIN "project_accesses" ON ("groups"."id" = "project_accesses"."group_id" OR "users"."id" = "project_accesses"."user_id")
现在的问题是,这只是一个传递给find_by_sql
的字符串,我无法弄清楚如何使它成为一个合适的Arel。
提前感谢您的帮助!
答案 0 :(得分:0)
您应该可以使用ARel的joins
方法手动构建您的联接,但仍然可以恢复实时关系。
http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-joins
答案 1 :(得分:0)
我越来越近了:
User.joins(:groups).joins("inner join project_accesses on (groups.id =
project_accesses.group_id or users.id = project_accesses.user_id)").
where(project_accesses: {project_id:1}).merge(Group.scoped).
merge(GroupMembership.scoped).merge(ProjectAccess.scoped).uniq
有没有办法在Arel中写这个部分?
joins("inner join project_accesses on (groups.id =
project_accesses.group_id or users.id = project_accesses.user_id)")
此外,是否有办法自动包含所有已加入模型的默认范围,以避免:
.merge(Group.scoped).merge(GroupMembership.scoped).merge(ProjectAccess.scoped)