Подтвердить что ты не робот

Сфера с присоединением: 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? Если нет, может кто-то порекомендовать решение?

4b9b3361

Ответ 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

Надеюсь, это поможет.