我有4个型号:Artists, Editions, Events & EventItems
。
对于艺术家,我有一个范围published
我将“活动”定义为处于状态为非draft
的事件的艺术家。
scope :published, -> { joins(:events).where("events.state != ?", 'draft').uniq }
这种方法很好,直到我开始链接它们,并希望艺术家至少参加特定版本published
的活动。
Edition.first.artists.published
除了它还会在当前版本之外加入events
并错误地发布艺术家(如果他们有任何已发布的事件(即使他们不在此特定版本中))之外,这是有效的。
为了让它正常工作,我必须像这样破解它(这太可怕了):
scope :published, ->(edition = nil) {
if edition.present?
joins(:events).where("events.state != ? AND events.edition_id = ?", 'draft', edition.id).uniq
else
joins(:events).where("events.state != ?", 'draft').uniq
end
}
Edition.first.artists.published(Edition.first)
有没有提供更多范围的上下文,只包括这个版本中的那些事件?那么它的范围会正确吗?
谢谢!
答案 0 :(得分:3)
恕我直言,问题依赖于您的关联和您正在生成的SQL,而不是您应该如何为范围提供上下文(传递参数是完全合法的)。
致电Event.artists
时,您已经加入了has_many :artists, through: :events
的活动以及加入events
的不加区别的活动。最重要的是,你依靠事件来确定艺术家是否活跃,如果不是SRP违规,这是另一个混乱的来源。
我认为解决方案来自于定义正确的关联:
class Edition
has_many :events
has_many :artists, through: :events
has_many :active_events, -> {where.not(state: "draft")}, class_name: "Events"
has_many :active_artists, through: :active_events,
class_name: "Artist",
source: :artists # => not sure if this option is necessary
end
class Events
has_many :event_items
has_many :artists, through: :event_items
end
Event.first.active_artists
我不是100%确定宏选项,但你明白了。