我有一个嵌套资源(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
答案 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查询,而不仅仅是像以前的解决方案那样进行查询,但是它可能更易于理解。