Rails habtm и поиск записи без ассоциации
У меня есть 2 модели:
class User < ActiveRecord::Base
has_and_belongs_to_many :groups
end
class Group < ActiveRecord::Base
has_and_belongs_to_many :users
end
Я хочу создать область (что важно - для эффективности и для возможности привязки областей), которая возвращает пользователей, которые не принадлежат группам ЛЮБОЙ.
После многих попыток мне не удалось выполнить метод вместо области видимости, что делает collect
on User.all
уродливым и не правильным.
Любая помощь?
И, возможно, для второго вопроса:
Мне удалось создать область, которая возвращает пользователей, принадлежащих к любой из заданных групп (заданных как массив идентификаторов).
scope :in_groups, lambda { |g|
{
:joins => :groups,
:conditions => {:groups => {:id => g}},
:select => "DISTINCT `users`.*" # kill duplicates
}
}
Может быть, лучше/красивее?
(Использование Rails 3.0.9)
Ответы
Ответ 1
Ваша неявная таблица соединений была бы названа groups_users
на основе соглашений об именах. Подтвердите это один раз в своем db. Предполагая, что это:
В новой версии 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.*"
}
Ответ 2
Если вы конвертируете из 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