我有一个父模型Effort has_many split_times:
class Effort
has_many :split_times
end
class SplitTime
belongs_to :effort
belongs_to :split
end
class Split
has_many :split_times
enum kind: [:start, :finish, :intermediate]
end
我需要一个范围来返回没有启动split_time的工作。这似乎应该是可能的,但到目前为止,我无法做到这一点。
我可以通过以下方式返回没有split_times的工作:
scope :without_split_times, -> { includes(:split_times).where(split_times: {:id => nil}) }
我可以返回至少有一个split_time的工作:
scope :with_split_times, -> { joins(:split_times).uniq }
这是我对我想要的范围的尝试:
scope :without_start_time, -> { joins(split_times: :split).where(split_times: {:id => nil}).where('splits.kind != ?', Split.kinds[:start]) }
但这不起作用。我需要一些能够返回没有split_time的所有努力的东西:即使努力有其他split_times,也要开始。我更喜欢Rails解决方案,但如果需要可以转到原始SQL。如果重要的话,我正在使用Postgres。
你可以在你的标准(即splits.kind = 'start'
)上保持连接,这将包括空值(即没有匹配的行加入)。区别在于Rails的join
默认情况下会给你一个内连接(两个表中都有匹配的行),但你需要一个左连接,因为你需要检查右表上没有匹配的行。
使用该连接的结果,您可以按事件分组,然后计算匹配拆分的数量 - 如果它为0,则该事件没有匹配的开始拆分!
这可能对你有用:
scope :without_start_time, -> {
joins("LEFT JOIN split_times ON split_times.effort_id = efforts.id").
joins("LEFT OUTER JOIN splits ON split_times.split_id = splits.id " \
"AND splits.kind = 0").
group("efforts.id").
having("COUNT(splits.id) = 0")
}