为类似的AR查询实现Query对象的正确方法

时间:2017-10-18 01:31:59

标签: ruby-on-rails ruby activerecord refactoring

我的rails应用程序模型中有两种方法。

sSendTo = Sheet1.Range.Columns(C) & lLastRow).Value 

如果我们可以从上面的方法中看到,两者都做了几乎相似的查询,唯一的区别是在Sub Jose_SendEmailDueDateReached() Dim OutApp As Object Dim OutMail As Object Dim lLastRow As Long Dim lRow As Long Dim sSendTo As String Dim sSendCC As String Dim sSendBCC As String Dim sSubject As String Dim sTemp As String Set OutApp = CreateObject("Outlook.Application") OutApp.Session.Logon ' Change the following as needed sSendTo = Sheet1.Range.Columns(C) & lLastRow).Value sSendCC = "Test@123.com" sSendBCC = "" sSubject = Range("A2").Value & " Progress Photos Due" lLastRow = Cells(Rows.Count, 3).End(xlDown).Row For lRow = 2 To lLastRow If Cells(lRow, 6) <> "Sent" Then If Cells(lRow, 5) <= Date Then Set OutMail = OutApp.CreateItem(0) On Error Resume Next With OutMail .To = sSendTo If sSendCC > "" Then .CC = sSendCC If sSendBCC > "" Then .BCC = sSendBCC .Subject = sSubject sTemp = "Hello," & vbCrLf & vbCrLf sTemp = sTemp & "The due date has been reached " sTemp = sTemp & "for this project:" & vbCrLf & vbCrLf ' Assumes project name is in column B sTemp = sTemp & " " & Cells(lRow, 2) & vbCrLf & vbCrLf sTemp = sTemp & "Please take the appropriate" sTemp = sTemp & " action." & vbCrLf & vbCrLf sTemp = sTemp & "Please forward photos to Test@greenscreen.com. " & vbCrLf & vbCrLf & vbCrLf & vbCrLf sTemp = sTemp & "Thank you." .Body = sTemp ' Change the following to .Send if you want to ' send the message without reviewing first .Display End With Set OutMail = Nothing Cells(lRow, 6) = "Sent" Cells(lRow, 7) = "E-mail sent on: " & Now() End If End If Next lRow Set OutApp = Nothing MsgBox ("Clear Stamp") Range("F2").ClearContents Range("G2").ClearContents MsgBox ("Stamp Cleared") End Sub 中有额外的连接和where 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 表的条件。

我读了一些文章,说这个特殊用例通常可以使用Query Object解决,但我想知道如何正确实现它?

我很感激的任何建议。

1 个答案:

答案 0 :(得分:0)

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