我试图让群组的用户使用非管理员的特定ID。
目前我有:
group.users
.joins(:roles)
.where(id: user_ids)
.where.not(roles: { role_type: Role::Type::ADMIN })
.pluck(:id)
在我的日志中,我有:
SQL加载group
:
(0.3ms) SELECT "users"."id" FROM "users" INNER JOIN "groups_users"
ON "users"."id" = "groups_users"."user_id"
WHERE "groups_users"."group_id" = $1 [["group_id", 137375]]
上述查询的SQL:
(0.6ms) SELECT "users"."id" FROM "users" INNER JOIN "roles"
ON "roles"."user_id" = "users"."id" AND "roles"."is_destroyed" = $1
INNER JOIN "groups_users" ON "users"."id" = "groups_users"."user_id"
WHERE "groups_users"."group_id" = $2 AND "users"."id" IN (82884, 82885)
AND "roles"."role_type" != $3 [["is_destroyed", "f"],
["group_id", 137375], ["role_type", 1]]
问题是我总是让该组的所有用户都匹配user_ids
。 where.not
无效。
我必须做类似
的事情users_in_group = group.users.where(id: user_ids).pluck(:id)
users_in_group -= group.users.joins(:roles).where
(roles: { role_type: Role::Type::ADMIN}).pluck(:id)
我不明白为什么。
答案 0 :(得分:2)
如果您想要排除管理员,即使他们有其他角色,您也可以使用SQL EXISTS
:
group.users
.where(id: user_ids)
.where("NOT EXISTS (SELECT 1 FROM roles WHERE user_id = users.id AND role_type = ?", Role::Type::ADMIN)
.pluck(:id)
而且,处理这些建议的典型异议:当你在Rails中使用ActiveRecord时,通过编写SQL片段来弄脏你的手是非常好的。你不应该限制自己的DSL(不是那么广泛)的可能性。
<强> UPD 强>
为简化您的代码,您可以使用Where Exists gem(披露:我最近写过)。
将gem 'where_exists'
添加到您的Gemfile中,运行bundle install
,然后以下内容应该有效:
group.users
.where(id: user_ids)
.where_not_exists(:roles, role_type: Role::Type::ADMIN)
.pluck(:id)