Rails ActiveRecord 模型范围与 has_many 关联的连接
Rails ActiveRecord model scope with joins on has_many associations
我目前正在我的 Rails 模型中设置一个范围,供 ActiveAdmin 使用。我要构建的范围应该找到每个 Job
过去有 survey_date
,现在有 Job.survey
,没有 Job.quotes
。
这是我的 Job
模型的简化版本:
has_many :quotes
has_many :surveys
scope :awaiting_quote, lambda { joins(:surveys, :quotes).where('survey_date < :current_time AND surveys.id IS NOT NULL AND quotes.id IS NULL', { current_time: Time.current }) }
我应该如何更改我的范围以使其正确找到相关的 Job
记录?
更新 Rails 5
如mad_raz mentions, in Rails 5.0+, you can use left_outer_joins
:
scope :awaiting_quote, -> { joins(:surveys).
left_outer_joins(:quotes).
where('survey_date < :current_time', { current_time: Time.current }).
where('quotes.id IS NULL')
}
但是,您仍然必须仅对 return 那些尚未收到报价的记录提供 where('quotes.id IS NULL')
检查。请参阅 以直观地了解外部联接。
将它们分成两个单独的范围可能仍然是最有意义的。
Rails 4
您可以使用 joins
创建左外部联接,您只需要更明确一点。
scope :awaiting_quote, -> { joins(:surveys).
joins('LEFT OUTER JOIN quotes ON quotes.job_id = jobs.id').
where('survey_date < :current_time', { current_time: Time.current }).
where('quotes.id IS NULL')
}
您不需要 surveys.id IS NOT NULL
,因为成功的内部联接不会包含 nil id。
将它们分成两个单独的范围可能更有意义,:has_survey
和 :without_quote
,然后可以将它们组合成一个方法。
def self.awaiting_quote
Job.has_survey.without_quote
end
Rails5介绍left_outer_joins
可以使用的方法
scope :awaiting_quote, -> { joins(:surveys).left_outer_joins(:quotes).where('yada yada') }
我目前正在我的 Rails 模型中设置一个范围,供 ActiveAdmin 使用。我要构建的范围应该找到每个 Job
过去有 survey_date
,现在有 Job.survey
,没有 Job.quotes
。
这是我的 Job
模型的简化版本:
has_many :quotes
has_many :surveys
scope :awaiting_quote, lambda { joins(:surveys, :quotes).where('survey_date < :current_time AND surveys.id IS NOT NULL AND quotes.id IS NULL', { current_time: Time.current }) }
我应该如何更改我的范围以使其正确找到相关的 Job
记录?
更新 Rails 5
如mad_raz mentions, in Rails 5.0+, you can use left_outer_joins
:
scope :awaiting_quote, -> { joins(:surveys).
left_outer_joins(:quotes).
where('survey_date < :current_time', { current_time: Time.current }).
where('quotes.id IS NULL')
}
但是,您仍然必须仅对 return 那些尚未收到报价的记录提供 where('quotes.id IS NULL')
检查。请参阅 以直观地了解外部联接。
将它们分成两个单独的范围可能仍然是最有意义的。
Rails 4
您可以使用 joins
创建左外部联接,您只需要更明确一点。
scope :awaiting_quote, -> { joins(:surveys).
joins('LEFT OUTER JOIN quotes ON quotes.job_id = jobs.id').
where('survey_date < :current_time', { current_time: Time.current }).
where('quotes.id IS NULL')
}
您不需要 surveys.id IS NOT NULL
,因为成功的内部联接不会包含 nil id。
将它们分成两个单独的范围可能更有意义,:has_survey
和 :without_quote
,然后可以将它们组合成一个方法。
def self.awaiting_quote
Job.has_survey.without_quote
end
Rails5介绍left_outer_joins
可以使用的方法
scope :awaiting_quote, -> { joins(:surveys).left_outer_joins(:quotes).where('yada yada') }