最近的排序问题回答并过滤了特定用户未回复的问题

时间:2015-09-29 20:46:47

标签: mysql ruby-on-rails activerecord ruby-on-rails-3.2

我在编写一个返回我想要的结果的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尚未回答的问题。< / p>

理想情况下,我想写

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链接起来,以及如何重写这个以便我能得到我想要的结果?感谢。

1 个答案:

答案 0 :(得分:1)

您应该在unanswered_by方法的SQL查询中添加表的名称:

  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结合使用,你的数据库适配器将不知道你从哪个表中选择了id(column id is ambiguous之类的错误消息)。

此外,您应该使用scope代替这两种方法。