获得使用params且没有其他人的用户

时间:2015-08-04 09:53:56

标签: sql ruby-on-rails ruby activerecord

我试图让群组的用户使用非管理员的特定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_idswhere.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)

我不明白为什么。

1 个答案:

答案 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)