我在ActiveRecord中构建此查询时遇到问题:
返回没有完成或活动打印作业的唯一文档列表。
因此,查询应包括根本没有打印作业或仅中止打印作业的文档。
以下是模型和相关属性:
class Document < ActiveRecord::Base
has_many :print_jobs
end
class PrintJob < ActiveRecord::Base
enum status: { active: 0, completed: 1, aborted: 2 }
belongs_to :document
end
我的第一次尝试是获取所有已完成或活动的打印作业的列表,并找到与这些打印作业无关的所有文档:
Document.where.not(id: PrintJob.active_or_completed.select(:document_id))
但我想知道这是否是正确的“SQL-ish”方式进行此类查询。
提前感谢您的帮助!
答案 0 :(得分:1)
我认为你这样做的方式绝对有道理。添加@Aleks建议的小优化:
picker.delegate = self
picker2.delegate = anotherClassInstance
编辑:更新以反映讨论的最新状态。删除了使用采摘的建议。这里没用。
答案 1 :(得分:0)
Document.joins(:print_jobs).where.not(status: [0,1]).uniq
应该完成这项工作。
答案 2 :(得分:0)
这是所有SQL方法,无需选择id's
并运行两个单独的查询:
Document.includes(:print_jobs).where.not( :print_jobs => { status: [statuses[:active], statuses[:completed]] } )
它将选择所有可以加入状态有效或已完成的PrintJobs
的文档
答案 3 :(得分:0)
我建议在Document模型中创建一个特殊范围,它只会返回所需的结果。因为您不应该将您的查询逻辑暴露出模型。 此外,最好将相应的范围添加到PrintJob模型中,这样就可以在Document for stroped PrintJob中定义额外的has_many关联。
正如Aleks已经提到的那样,最好在数据库层上完成所有工作并且不要提取PrintJob的所有ID并将它们传递给查询,因为它可能会降低性能显著。因此,使用单个SQL查询进行此操作会更好。
class Document < ActiveRecord::Base
has_many :print_jobs
# Here we can define association with scope which applies scope defined in PrintJob
has_many :not_active_or_completed_print_jobs, -> { not_active_or_completed }, class_name: 'PrintJob'
# I believe that there is a shorter name exists for such sort of documents
def self.without_active_or_completed_jobs
distinct.joins(:not_active_or_completed_print_jobs)
end
end
class PrintJob < ActiveRecord::Base
enum status: { active: 0, completed: 1, aborted: 2 }
belongs_to :document
def self.not_active_or_completed
where.not(status: [statuses[:active], statuses[:completed]])
end
end
之后你可以这样称呼它:
Document.without_active_or_completed_jobs