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
表没有加入/条件。< / p>
问题是,如果current_user
和another_user
都是某个Meetings
实例的参与者,则会为每个参与者返回结果集中的Meetings
条记录已将hidden
设置为false
的人。如果current_user
为所有true
设置了hidden
Meetings
,则another_user
是hidden
设置为false
的任何相同会议的参与者Meetings
Meetings.visible
User
将显示在{{1}}结果集中。
是否可以使用上面提到的范围,它将正确加入{{1}}实例?如果没有,有人可以推荐一个解决方案吗?
答案 0 :(得分:82)
这是我解决您问题的方法:
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
@user.meetings.visible
答案 1 :(得分:59)
在Rails 4中,您可以在关联本身中指定最初在子对象中定义的范围。简而言之:您无需了解User模型中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
具有不同的结果集
答案 2 :(得分:7)
def belongs_to_user_in_pending_state(user)
if self.user_items.pending.select {|s| s.user == user}.count > 0
return true
else
return false
end
end
答案 3 :(得分:1)
这是一个班轮:
Meeting.joins(:meeting_participations).where(meeting_participation: { hidden: false, user_id: current_user.id })
这很棒,因为你可以用它制作一个范围,一个函数,或者只是在任何地方调用它。您还可以向哈希添加任何您想要的限制。
答案 4 :(得分:1)
干净,关联的方法是:
has_many :visible_meetings, -> { merge(MeetingParticipations.visible) },
:source => :meeting, :through => :meeting_participations
用更笼统的术语来说:如果您有一个链接的has_many
关联,则可以通过合并作用域来定义中间(through
)关联。可能需要Rails 4 +。
否则,必须通过创建(可能是不需要的)中间作用域关联来完成,如@Paul Pettengill的回答所示。
答案 5 :(得分:0)
我知道这个问题已在不久前得到解答,但我刚刚遇到了类似的问题,并且正在寻找解决该问题的最佳方法。公认的解决方案非常简单,但我认为将关联的范围从Users
移到Meeting
会更清洁,如下所述
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
scope :hidden, -> { where('meeting_participations.hidden = ?', true) }
scope :visible, -> { where('meeting_participations.hidden = ?', false) }
end
class MeetingParticipations < ActiveRecord::Base
belongs_to :user
belongs_to :meeting
scope :hidden, where(:hidden => true)
scope :visible, where(:hidden => false)
end
这样,您就可以呼叫current_user.meetings.hidden
根据设计,会议现在指示隐藏/可见的原因。
答案 6 :(得分:-3)
在我看来,为了您的目的而在会议上使用范围是不明智的。会议本身没有可见性,但参与有。所以我建议对用户内的关联进行扩展:
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
我希望,这有帮助。
答案 7 :(得分:-3)
你也可以这样做:
current_user.meeting_participations.visible.map(&:meeting)