Rails 3 Scope - Find users not in a specific group

元气小坏坏 提交于 2019-12-08 03:52:41

问题


Here is my problem (a bit simplified) :

I've got the following models :

class User
has_many :group_users
has_many :groups, through: :group_users


class Group
has_many :group_users
has_many :users, through: :group_users


class GroupUser
belongs_to :group
belongs_to :user
scope :belonging_to_group ->(group) {where(group_id = group.id)}

I would like to scope users that are not in one specific group, let's say veggies for examples, something that would begin like this :

scope :not_in_group, ->(group)

I've tried stuffs with having clauses like that:

scope :not_in_group, ->(group) {joins(:group_users).merge(::GroupUser.belonging_to_group(group)).group(:title).having('count(group_users.user_id) = 0')

but nothing seems to work

EDIT : I've got another problem now, you may want to check this if you're calling your scope from an other class' class method : Rails - Use a class method from a another class method with one attribute of the second class


回答1:


Try This

scope :not_in_group, -> group_id {joins(:group_users).where('group_users.group_id != ?', group_id)}

For left join, try this:

scope :not_in_group, -> group_id {joins("left join group_users on users.id = group_users.user_id").where('group_users.group_id != ?', group_id)}



回答2:


According to the rails documentation:

Using a class method is the preferred way to accept arguments for scopes. These methods will still be accessible on the association objects. source.

class User
#...
    # Retrieve all users not in a specific group
    # example: User.not_in_group(Group.find(5))
    def self.not_in_group(group)
        includes(:group_users).where("group_users.group_id != ?", group.id)
    end
end

If you are determined to use a scope, here it is:

scope :not_in_group, ->(group) {includes(:group_users).where("group_users.group_id != ?", group.id)}



回答3:


EDIT : I realised that it was not working fine if a user had 2 groups, as he would appear as not in both. I believe that MySQL found an other group_users with the user's id and the other group_id.

So I changed to this, which seems to work :

scope :not_in_group, ->(group){
  in_group = User.joins(:group_users).where("group_users.group_id = ?", group.id)
  where(arel_table[:id].not_in in_group.map(&:id))
}

In two times but working.

Previous solution : only works if your user has one group.

Finally I found a solution, I had to pass raw SQL in joins() and where() as @Himesh suggested me to do. Thanks a lot to you and @lightswitch05 for your help.

Both of your propositions did not select the users without any group, here is a solution that works :

  def not_in_group(group)
    joins('LEFT JOIN group_users ON group_users.user_id = users.id').where("group_users.group_id != ? OR group_users.group_id is null", group.id)
  end

Found some held there : Rails 3 ActiveRecord where clause where id is set or null



来源:https://stackoverflow.com/questions/24186472/rails-3-scope-find-users-not-in-a-specific-group

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!