2015-05-19 119 views
1

我目前正在Rails模型中設置一個作用域以供ActiveAdmin使用。我想構建的範圍應該會找到每個Job,它們過去都有survey_date,目前有Job.survey,並且沒有Job.quotesRails ActiveRecord模型範圍與has_many關聯上的連接

這裏是我的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 }) } 

我應該如何改變我的範圍,使其正確地找到revelant Job記錄?

+1

請注意'joins'將創建一個INNER JOIN,這意味着'quotes.id IS NULL'沒有影響,並且這些作業永遠不會顯示try'includes(:surveys,:quotes).where(' survey_date <:current_time AND surveys.id IS NOT NULL AND quotes.id IS NULL',{current_time:Time.current})'這將創建2個LEFT OUTER JOIN,並且可能對您更好。關於關聯加載以及這些方法如何工作,這是一篇很棒的[文章](http://blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html) – engineersmnky

回答

3

您可以使用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 ids。

將它們拆分爲兩個單獨的作用域:has_survey:without_quote可能更有意義,然後它們可以組合成一個方法。

def self.awaiting_quote 
    Job.has_survey.without_quote 
end 
+0

太好了,謝謝! – gosseti