使用连接表排除随机查询中出现的记录

时间:2014-01-11 22:19:24

标签: ruby-on-rails ruby postgresql

我正在使用rails应用程序,其中向用户呈现来自用户所选类别的随机问题。如果用户已经回答了问题,我希望它永远不会再次呈现给用户。

问题的答案存储在记忆表中。存储器表充当用户和问题之间的连接表。在rails控制台中,我可以使用question = Question.first隔离已回答特定问题的所有用户,而question.users将返回已回答该问题的用户对象数组。

在rails中,我无法弄清楚如何排除已回答的问题再次出现。

指导?

作为一个抬头,我大约有12个星期进入我的rails / ruby​​开发。我怀疑这很容易让我看不到它。

我的QuestionsController - 这可以呈现一个随机问题,但即使用户之前已经回答了问题,也会出现:

class QuestionsController < ApplicationController

  def index
   @category = Category.find(params[:category_id])
   @question = Question.where(category_id: @category.id).sample
  end

  def show
   @question = Question.find(params[:id])
  end

end

问题模型

class Question < ActiveRecord::Base
  validates_presence_of :category_id

  has_many :memories,
    inverse_of: :question

  has_many :users,
    through: :memories

  belongs_to :category,
    inverse_of: :questions

end

用户模型

class User < ActiveRecord::Base
  validates_presence_of :first_name, :last_name, :role

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

  def is_admin?
    role == 'admin'
  end

  has_many :memories,
    inverse_of: :user,
    dependent: :destroy

  has_many :questions,
    through: :memories

end

内存模型

class Memory < ActiveRecord::Base
  validates_presence_of :user, :question

  belongs_to :question,
    inverse_of: :memories

  belongs_to :user,
    inverse_of: :memories

  validates :question, uniqueness: { :scope => :user }

end

我的记忆模型中的验证会阻止用户回答他们已经回答过的问题 - 这是朝着正确方向迈出的一步。我想这个问题一旦回答就再也不会出现了。

这是我在这里的第一篇文章。很高兴加入社区,并希望有一天能够支付它。谢谢你的任何指导。

2 个答案:

答案 0 :(得分:2)

你可以尝试

@question = Question.where(category_id: @category.id)
  .where("id NOT IN(select question_id from memories where user_id = ?)", current_user.id)
  .sample

答案 1 :(得分:1)

您的问题中有两个相当复杂的问题需要解决。

首先是记录的正确随机化,你可以在SO上找到很多好的答案:

第二种方法是选择不通过关系排除记录而关联的数据。

您可以通过子查询执行此操作:Rails exclusion query with active record -- Rails 3.1

或通过外部联接:Finding records with no associated records in rails 3

作为旁注:

努力始终使用ActiveRecords关系,因此@category.questions代替Question.where(category_id: @category.id)

如果通过范围正确实现随机化和选择,应该可以编写简洁的代码,如:

@questions = @category.questions.unanswered(current_user.id).random