0
votes

I have two methods in my rails app model.

def questions_mastered_for(user_id, question_group_ids)
  res = UserAnswer
          .joins('INNER JOIN question_group_questions ON user_answers.question_id = question_group_questions.question_id')
          .joins('INNER JOIN marks ON user_answers.id = marks.user_answer_id')
          .group('question_group_questions.question_group_id')
          .where(question_group_questions: { question_group_id: question_group_ids })
          .where(user_answers: { user_id: user_id })
          .where("(marks.boolean_mark_correct = true AND marks.mark_type = 'boolean') OR (marks.fraction_numerator = marks.fraction_denominator AND marks.mark_type = 'fraction')")
          .pluck('question_group_questions.question_group_id', 'COUNT(DISTINCT(user_answers.question_id))')

  question_group_mastery = {}
  question_group_ids.each { |question_group_id| question_group_mastery[question_group_id] = 0 }
  res.each { |data| question_group_mastery[data.first] = data.second }

  question_group_mastery
end

def questions_attempted_for(user_id, question_group_ids)
  res = UserAnswer
          .joins('INNER JOIN question_group_questions ON user_answers.question_id = question_group_questions.question_id')
          .group('question_group_questions.question_group_id')
          .where(question_group_questions: { question_group_id: question_group_ids })
          .where(user_answers: { user_id: user_id })
          .pluck('question_group_questions.question_group_id', 'COUNT(DISTINCT(user_answers.question_id))')

  question_group_attempted = {}
  question_group_ids.each { |question_group_id| question_group_attempted[question_group_id] = 0 }
  res.each { |data| question_group_attempted[data.first] = data.second }

  question_group_attempted
end

If we can see from above methods, both do almost similar query the only difference is in questions_mastered_for there is additional join and where condition to marks table.

I read some articles that this particular use case usually can be resolved using Query Object, but I wonder how to implement it correctly?

Any suggestions I kindly appreciate.

1

1 Answers

0
votes
def questions_attempted_for_query(user_id, question_group_ids)
  UserAnswer
          .joins('INNER JOIN question_group_questions ON user_answers.question_id = question_group_questions.question_id')
          .group('question_group_questions.question_group_id')
          .where(question_group_questions: { question_group_id: question_group_ids })
          .where(user_answers: { user_id: user_id })
end
def questions_mastered_for(user_id, question_group_ids)
  res = questions_attempted_for_query(user_id, question_group_ids)
          .joins('INNER JOIN marks ON user_answers.id = marks.user_answer_id')
          .where("(marks.boolean_mark_correct = true AND marks.mark_type = 'boolean') OR (marks.fraction_numerator = marks.fraction_denominator AND marks.mark_type = 'fraction')")
          .pluck('question_group_questions.question_group_id', 'COUNT(DISTINCT(user_answers.question_id))')

  question_group_mastery = {}
  question_group_ids.each { |question_group_id| question_group_mastery[question_group_id] = 0 }
  res.each { |data| question_group_mastery[data.first] = data.second }

  question_group_mastery
end

def questions_attempted_for(user_id, question_group_ids)
  res = questions_attempted_for_query(user_id, question_group_ids)
          .pluck('question_group_questions.question_group_id', 'COUNT(DISTINCT(user_answers.question_id))')

  question_group_attempted = {}
  question_group_ids.each { |question_group_id| question_group_attempted[question_group_id] = 0 }
  res.each { |data| question_group_attempted[data.first] = data.second }

  question_group_attempted
end