Rails获取与布尔值匹配的父资源的第一个嵌套资源

时间:2018-10-24 07:42:01

标签: ruby-on-rails

我有一个嵌套资源(user_answer),该资源引用了父级资源(multiple_choice_question)。每个用户可以根据需要尝试多次multi_choice_question,系统会保存每次点击时的user_answer。

但是,我希望能够向用户展示他们在首次提交user_answer时有多少个独特的问题。

例如;在100个问题中,用户在第一次尝试时就回答了33个问题。 (基于.first或created_at,基于时间)

我写了这个查询,但这是不正确的。不确定如何针对需要的内容使其更具体。

@correct_on_first_attempt = @user.user_answers.where(:is_correct_answer => true).distinct.count(:multiple_choice_question_id).first

UserAnswer模型

# == Schema Information
#
# Table name: user_answers
#
#  id                          :bigint(8)        not null, primary key
#  user_id                     :integer
#  multiple_choice_question_id :integer
#  selected_answer             :text
#  is_correct_answer           :boolean
#  created_at                  :datetime         not null
#  updated_at                  :datetime         not null
#
class UserAnswer < ApplicationRecord
  belongs_to :user
  belongs_to :multiple_choice_question
end

MultipleChoiceQuestion模型

class MultipleChoiceQuestion < ApplicationRecord
  belongs_to :user, optional: true
  validates :user, presence: true

has_many :user_answers
has_many :users, through: :user_answers

1 个答案:

答案 0 :(得分:1)

因此,首先,我认为您在实际上不需要.first时将其放在最后。我认为删除该漏洞将解决您面临的错误。添加.first并不会真正获取每组条目的第一个结果。它试图从整数中提取“第一个”结果,但这实际上是不可能的。

其次,您的查询:@correct_on_first_attempt = @user.user_answers.where(:is_correct_answer => true).distinct.count(:multiple_choice_question_id)尝试查找用户到目前为止已正确回答的问题总数,而对首次尝试没有任何条件。

如果要查找用户是否能够在第一次尝试中解决问题,那是通过SQL稍微难一点的解决方案,因为您需要找到用户为每个问题提供的最早答案。

取决于您的数据库,可以使用多种解决方案。在每种情况下,我建议您自己编写SQL查询并执行它,而不是使用Rails的辅助函数,因为ActiveRecord不能为您的用例提供足够的通用性。

示例SQL查询:

SELECT COUNT(DISTINCT multiple_choice_question_id) FROM
  (
    SELECT multiple_choice_question_id,
           user_id,
           ROW_NUMBER () OVER (
             PARTITION BY multiple_choice_question_id
             ORDER BY created_at
           ) AS rn
    FROM user_answers
    WHERE user_id = 4
    AND is_correct_answer = TRUE
  )
  WHERE rn = 1

您必须对此进行一次测试;我还没有检查。

编辑:更多Rails-ey解决方案:

distinct_question_ids = @user.user_answers.
  where(is_correct_answer: true).
  distinct.pluck(:multiple_choice_question_id)

@correct_on_first_attempt = distinct_question_ids.select { |qid|
  @user.user_answers.
    where(multiple_choice_question_id: qid).first.is_correct_answer
}.count

这不是一个好的解决方案,因为它实际上可以进行许多SQL查询,而不仅仅是像以前的解决方案那样进行查询,但是它可能更易于理解。