我有一个任务管理应用程序,用户可以在其中创建任务的"等待"。 如果他们正在等待的项目尚未收到,则任务仍处于活动状态。
我正在尝试设置"可操作"范围以包括以下任务:
- 有一个waiting_for,received_date不是零(他们等待的任何东西都被收到了)
或 -
没有等待
class Task < ActiveRecord::Base has_many :waiting_fors def self.actionable where("snooze_date <= ? OR snooze_date IS ?", Time.now, nil ).where(complete: false) .includes(:waiting_fors).where("waiting_fors.received_date IS NOT ?", nil) end class WaitingFor < ActiveRecord::Base belongs_to :task end
但是,它向下过滤以仅向我显示项目具有waiting_for的位置以及waiting_for具有received_date的位置。
有什么不好说我哪里错了?
更新:
这就是我现在所拥有的。 如果任务没有等待或有一个等待已收到,则它正在工作。
scope :not_snoozed, -> {where("snooze_date <= ? OR snooze_date IS ?", Time.now, nil)}
scope :incomplete, -> {where(complete: false)}
scope :no_waiting_fors, -> {includes(:waiting_fors).where(waiting_fors: {id: nil})}
scope :not_received, -> {includes(:waiting_fors).where.not(waiting_fors: {received_date: nil})}
scope :actionable, -> {incomplete.not_snoozed.where(id: (Task.no_waiting_fors+Task.not_received).map(&:id))}
但是,如果一个任务有两个waiting_fors并且只有一个有接收日期(这意味着我们仍在等待某些内容),则它将显示为活动状态。
尝试使用 SQL 的 NOT IN 功能将作用域更新为此:
scope :received, -> {includes(:waiting_fors).where("tasks.id not in (select tasks.id from tasks inner join waiting_fors on waiting_fors.task_id = tasks.id where waiting_fors.received_date is null)")}
scope :actionable, -> {incomplete.not_snoozed.where(id: (Task.no_waiting_fors+Task.received).map(&:id))}
你的意思是
where("waiting_fors.received_date = ?", nil)
而不是
where("waiting_fors.received_date IS NOT ?", nil)
所有这些都可以通过命名范围轻松实现。您可以为不同的条件构造一个范围,如果要使用多个条件,则可以组合范围。你使用的是 Rails 4 吗?这将是语法:
class Task < ActiveRecord::Base
has_many :waiting_fors
scope :no_waiting_fors, -> {includes(:waiting_fors).where(waiting_fors: {id: nil})}
scope :not_received, -> {includes(:waiting_fors).where.not(waiting_fors: {received_date: nil})}
scope :actionable, -> {where(id: (Task.no_waiting_fors+Task.not_received).map(&:id))}
end
像这样,您将获得灵活且可扩展的配置。