我有2个型号:
class User < ActiveRecord::Base
has_and_belongs_to_many :groups
end
class Group < ActiveRecord::Base
has_and_belongs_to_many :users
end
我想制作一个范围(这对于效率和链接范围的能力很重要),它会返回不属于 ANY 组的用户。
经过多次尝试,我没有做一个方法而不是范围,这使collect
上的User.all
变得丑陋而且......不对。
任何帮助?
也许是第二个问题: 我设法创建一个范围,返回属于任何给定组的用户(以id的数组形式给出)。
scope :in_groups, lambda { |g|
{
:joins => :groups,
:conditions => {:groups => {:id => g}},
:select => "DISTINCT `users`.*" # kill duplicates
}
}
可以更好/更漂亮吗? (使用Rails 3.0.9)
答案 0 :(得分:17)
根据命名约定,您的隐式连接表将被命名为groups_users
。在数据库中确认一次。假设它是:
在较新的Rails版本中:
scope :not_in_any_group -> {
joins("LEFT JOIN groups_users ON users.id = groups_users.user_id")
.where("groups_users.user_id IS NULL")
}
对于较旧的Rails版本:
scope :not_in_any_group, {
:joins => "LEFT JOIN groups_users ON users.id = groups_users.user_id",
:conditions => "groups_users.user_id IS NULL",
:select => "DISTINCT users.*"
}
答案 1 :(得分:3)
如果您从HABTM转换为has_many到(更灵活)关联,那么您可以使用以下内容:
class Group < ActiveRecord::Base
has_many :groups_users, dependent: :destroy
has_many :users, through: :groups_users, uniq: true
scope :in_groups, -> { includes(:groups_users).where(groups_users: {group_id: nil}) }
end
class User < ActiveRecord::Base
has_many :groups_users, dependent: :destroy
has_many :groups, through: :groups_users
end
class GroupsUser < ActiveRecord::Base
belongs_to :group
belongs_to :user
end
答案 2 :(得分:0)
在 Rails >= 5 中,有 left_outer_joins,结合 new(ish) .where()
语法,使范围更具可读性:
class User < ActiveRecord::Base
has_and_belongs_to_many :groups
scope :not_in_any_group, -> {
left_outer_joins(:groups)
.where(groups_users: { user_id: nil })
}
end
class Group < ActiveRecord::Base
has_and_belongs_to_many :users
end