Сфера с присоединением: has_many: через объединение
class Users < ActiveRecord::Base
has_many :meetings, :through => :meeting_participations
has_many :meeting_participations
end
class Meetings < ActiveRecord::Base
has_many :users, :through => :meeting_participations
has_many :meeting_participations
end
class MeetingParticipations < ActiveRecord::Base
belongs_to :user
belongs_to :meeting
scope :hidden, where(:hidden => true)
scope :visible, where(:hidden => false)
end
hidden
является дополнительным булевым столбцом в таблице связей m2m. Учитывая некоторый Users
экземпляр current_user
, я хочу сделать
current_user.meetings.visible
который будет извлекать коллекцию Meetings
, для которой пользователь является участником, где столбец hidden
равен false
. Самое близкое, что я получил, добавляет следующую область в класс Meetings
scope :visible, joins(:meeting_participations) & MeetingParticipation.visible
scope
фильтрует Meetings
по таблице MeetingParticipations
, однако нет соединения/условия в отношении таблицы MeetingParticipations
, связанной с current_user
.
Проблема заключается в том, что если current_user
и another_user
являются участниками для экземпляра Meetings
, запись Meetings
в результирующем наборе будет возвращена для каждого участника, у которого hidden
установлено значение false
. Если current_user
имеет true
для hidden
для hidden
для всех Meetings
, если another_user
является участником любого из тех же совещаний с hidden
, установленным на false
, те Meetings
появятся в Meetings.visible
набор результатов.
Возможно ли иметь область видимости, как я уже упоминал выше, которая будет правильно присоединяться к экземпляру User
? Если нет, может кто-то порекомендовать решение?
Ответы
Ответ 1
Это мое решение для вашей проблемы:
class User < ActiveRecord::Base
has_many :meeting_participations
has_many :meetings, :through => :meeting_participations do
def visible
where("meeting_participations.visible = ?", true)
end
end
end
Ответ 2
В Rails 4 вы можете указать область, первоначально определенную в дочернем объекте в самой ассоциации. Короче: вам не нужно знать внутренности модели MeetingParticipation в модели пользователя.
class User < ActiveRecord::Base
has_many :meeting_participations
has_many :meetings, :through => :meeting_participations
has_many :visible_participations, -> { visible }, :class_name => 'MeetingParticipation'
has_many :visible_meetings, :source => :meeting, :through => :visible_participations
end
class Meeting < ActiveRecord::Base
has_many :meeting_participations
has_many :users, :through => :meeting_participations
end
class MeetingParticipation < ActiveRecord::Base
belongs_to :user
belongs_to :meeting
scope :hidden, -> { where(:hidden => true) }
scope :visible, -> { where(:hidden => false) }
end
Это позволит вам сделать: user1.visible_meetings
и user2.visible_meetings
с различными наборами результатов
Ответ 3
current_user.meetings.merge(MeetingParticipations.visible)
Ответ 4
Здесь один лайнер:
Meeting.joins(:meeting_participations).where(meeting_participation: { hidden: false, user_id: current_user.id })
Это здорово, потому что вы можете сделать из него объем, функцию из нее или просто называть ее где угодно. Вы также можете добавить любые ограничения, которые вы хотите использовать для хэша.
Ответ 5
Вы также можете сделать:
current_user.meeting_participations.visible.map(&:meeting)
Ответ 6
Мне кажется, что разумно использовать сферу действия на Собрании для вашей цели. Сама встреча не имеет видимости, но участие имеет. Поэтому я бы предложил расширение в ассоциации в User:
class User < ActiveRecord::Base
has_many :meetings, :through => :meeting_participations do
def visible
ids = MeetingParticipation.
select(:meeting_id).
where(:user_id => proxy_owner.id, :visible => true).
map{|p| p.meeting_id}
proxy_target.where("id IN (?)", ids)
end
end
...
end
Надеюсь, это поможет.