#ruby-on-rails #activerecord #has-many-through
Вопрос:
Рассмотрим 3 модели: Пользователь, Группа и членство в группе
class User < ApplicationRecord
has_many :group_memberships
has_many :groups, through: :group_memberships
end
class Group < ApplicationRecord
has_many :group_memberships
has_many :users, through: :group_memberships
end
class GroupMembership < ApplicationRecord
belongs_to :user
belongs_to :group
scope :current, -> { where(active_at: [nil, (..Time.current)], expires_at: [nil, (Time.current..)]) }
end
Ничего примечательного в пользователе или группе, но у GroupMembership есть два столбца даты и времени, которые определяют, является ли членство текущим: active_at и expire_at. Моя логика заключается в том, что Пользователь является членом группы в данный момент времени, пока active_at <= point_in_time
Я не хочу устанавливать область по умолчанию для GroupMembership, но я бы хотел, чтобы ассоциации has_many включали только текущие объединения.
Я попытался добавить :текущую область (которая определена для членства в группе) в «Принадлежность» в членстве в группе, и я попытался добавить :текущую область в has_many :через группу и пользователя, и каждый подход приводит к ошибкам при попытке найти как группы Пользователей, так и пользователей Группы.
Как мне заставить эти отношения работать так, как задумано?
Отредактировано: Я изначально опустил has_many :group_memberships в своих моделях для этого вопроса, после добавления вопрос почти ответил сам на себя — область, которая существует в модели GroupMembership, относится к has_many :group_memberships моделей пользователей и групп.
Ответ №1:
Не уверен в этом, но вы можете попробовать следующее. В модели пользователя или группы вы можете создать новую функцию для выполнения запроса, а затем просто получить ее. Я не уверен на 100% в синтаксисе, но это что-то вроде этого:
class User < ApplicationRecord
has_many :group_memberships
has_many :groups, through: :group_memberships
def self.current
self.joins(:group_memberships).where(active_at: [nil, (..Time.current)], expires_at: [nil, (Time.current..)])
end
end
Затем в своем контроллере вы можете сделать:
User.current
Комментарии:
1. Извините — пожалуйста, посмотрите мои правки и ответьте. Я полагаю, что мой первоначальный вопрос ввел вас в заблуждение. Увидев ваш ответ, я понял как свою ошибку, так и правильный ответ.
Ответ №2:
Добавление области действия в has_many :group_memberships как в пользовательской, так и в групповой моделях делает именно то, что требуется.
class User < ApplicationRecord
has_many :group_memberships, -> { current }
has_many :groups, through: :group_memberships
end
class Group < ApplicationRecord
has_many :group_memberships, -> { current }
has_many :users, through: :group_memberships
end