2015-09-29 52 views
1

我在寫一個Active Record查詢時遇到問題,該查詢返回我想要的結果。我有以下設置:排序問題最近回答和篩選特定用戶未回答的問題

刪節User型號:

class User < ActiveRecord::Base 
    has_many :answers 
end 

刪節Answer型號:

class Answer < ActiveRecord::Base 
    belongs_to :question 
    belongs_to :user 
end 

刪節Question型號:

class Question < ActiveRecord::Base 
    has_many :answers 

    def self.unanswered_by(user) 
    where(
     'id NOT IN (SELECT question_id FROM answers WHERE user_id = ?)', 
     user.id 
    ) 
    end 

    def self.recently_answered 
    includes(:answers).order('answers.updated_at DESC') 
    end 
end 

我試圖得到一個ActiveRecord::Relation退回訂單那些最近被回答的問題,然後過濾結果,因此它只包含問題current_user尚未回答。

理想情況下,我想寫

Question.recently_answered.unanswered_by current_user 

但是這似乎並沒有工作,我掙扎與我有限的SQL的認識理解爲什麼。

這是結果我得到的,當我在Rails的控制檯運行此:

me = User.find(8) 
Question.recently_answered.unanswered_by me 
=> SQL (0.5ms) SELECT `questions`.`id` AS t0_r0, 
    `questions`.`question_text` AS t0_r1, 
    `questions`.`example_answer` AS t0_r2, 
    `questions`.`created_at` AS t0_r3, 
    `questions`.`updated_at` AS t0_r4, 
    `answers`.`id` AS t1_r0, 
    `answers`.`question_id` AS t1_r1, 
    `answers`.`user_id` AS t1_r2, 
    `answers`.`answer_text` AS t1_r3, 
    `answers`.`created_at` AS t1_r4, 
    `answers`.`updated_at` AS t1_r5 
    FROM `questions` LEFT OUTER JOIN `answers` 
    ON `answers`.`question_id` = `questions`.`id` 
    WHERE (id NOT IN (SELECT question_id FROM answers WHERE user_id = 8)) 
    ORDER BY answers.updated_at DESC 
    #<ActiveRecord::Relation:0x3fd42e362a80> 

運行Question.recently_answered.unanswered_by(me).to_sql給了我這樣的:

=> "SELECT `questions`.* 
    FROM `questions` 
    WHERE (id NOT IN (SELECT question_id 
      FROM answers WHERE user_id = 8)) 
    ORDER BY answers.updated_at DESC" 

我解決這個正確的工作,現在通過做

Question 
    .recently_answered 
    .reject { |q| q.answers.map(&:user_id).include? current_user.id } 

但是這返回ArrayQuestion對象,而不是我喜歡的ActiveRecord::Relation

有人可以幫助我理解爲什麼我不能連鎖recently_answeredunanswered_by爲書面,我怎麼可以重寫這個,所以我可以得到我想要的結果?謝謝。

def self.unanswered_by(user) 
    where('questions.id NOT IN (SELECT question_id FROM answers WHERE user_id = ?)', user.id) 
      #^^^^^^^^^ table's name added here 
    end 

因爲如果你使用這個具有joins/includes相結合,你的數據庫適配器會不知道從您選擇哪個表:

+2

在'unanswered_by'方法的實現中,'id'列可能不明確(如果你加入的話)。在'id'之前使用表名,以確保沒有對'id'列的模糊調用(使用'questions.id NOT IN ...') – MrYoshiji

+1

另外,這些方法應該定義爲'scope'(在你的case:'scope:recent_answered, - > {includes(:answers).order('interview_answers.updated_at DESC')}') – MrYoshiji

+0

@MrYoshiji謝謝。現在你指出'id'在'unanswered_by'方法中是不明確的。當我按照你的建議去做'questions.id不是...'的時候,它就會起作用。請在這裏使用範圍而不是類方法。我會重寫它們。添加爲答案,我很樂意接受。再次感謝幫助我理解。 –

回答

1

你應該在unanswered_by方法的SQL查詢添加表的名稱編號(錯誤信息如column id is ambiguous)。

此外,您應該使用scope代替這兩種方法。