我的代码应该从QUIZ(MyQuiz)中获取答案(真),并将其与Root类型进行比较。测验问题具有通过RootProfile关联的类型(名称)。例如,
question.root_profile.name
将返回类似的内容:
{question: "1", name: "ocean", ...}
我应该知道我也有什么类型的答案。
answer.question.root_profile.name
当我从MyQuiz获得所有真实答案时,我可能拥有10个Ocean 6鸟3轮胎。然后,基于此,我计算了每个小测验相对于整个测验的百分位数。如果测验有100个问题,它将计算出10%的海洋,6%的鸟类和3%的轮胎。
代码如下:
module RootServices
class RootCount
def initialize (my_quiz)
@my_quiz = my_quiz
end
attr_reader :my_quiz
def root_counts(root_profile)
total = []
all_answers.each do |answer|
if answer.question.root_profile.name == root_profile.name
total << answer
end
end
total_percentage = (total.count.to_f / all_answers.count.to_f) * 100
element = {root_profile_id: root_profile.id, root_profile: root_profile.name, total: total_percentage}
return element
end
def root_branch
root_branch_total = []
# Pass root_profile object to root_counts and store in the root_branch_total array of hashes the returned element
root_profiles.each do |root_profile|
root_branch_total << root_counts(root_profile)
end
return root_branch_total
end
def root_profiles
title = RootProfile.all
end
def all_answers
all_answers = my_quiz.my_answers.where(answer: true)
end
end
end
它可以工作,但是有点复杂,循环似乎是多余的。我想知道是否会有更优雅的方法。我的逻辑工作正常,但是我的日志显示来自Answers = true的查询(假设我的测试具有五个true),其中五个查询针对RootProfile,五个查询针对Question Nested。这是一个视觉效果:
SELECT "my_answers".* FROM ...
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "my_answers".* FROM ...
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
SELECT "questions".* FROM "questions"
SELECT "root_profiles".* FROM "root_profiles"
...
3x more
编辑:添加经过修改的代码行
module RootServices
class RootCount
def initialize (my_quiz)
@my_quiz = my_quiz
@root_profiles = RootProfile.all
@all_answers = @my_quiz.my_answers.where(answer: true)
end
def root_branch
root_profiles.map { |root_profile| root_counts(root_profile) }
end
private
attr_reader :my_quiz, :root_profiles, :all_answers
def root_counts(root_profile)
answers = matching_answers(root_profile)
{
root_profile_id: root_profile.id,
root_profile: root_profile.name,
total: percentage_of_total(answers)
}
end
def matching_answers(root_profile)
all_answers.joins(question: :root_profile).where("root_profiles.name = ?", root_profile.name)
end
def percentage_of_total(answers)
(answers.count.to_f / all_answers.count.to_f) * 100
end
end
end
答案 0 :(得分:2)
首先,我认为您可能会丢失ruby的几个核心概念-最明显的是隐式返回-对于您的代码,这意味着您不需要在return
语句在方法的最后,您无需在单行代码中分配给局部变量。 Ruby就是那样的好。
您可以通过将要比较的所有名称收集到一个查询中来减少查询,而不必重复调用answer.question.root_profile.name
。此外,您可能应该在SQL中进行选择,而不是立即将其转换为数组。我将为您重构一些方法,以提供一个示例,说明如何更好地做到这一点。类似于以下内容
def root_counts
answers = matching_answers(root_profile)
{
root_profile_id: root_profile.id,
root_profile: root_profile.name,
total: percentage_of_total(answers)
}
end
private
def root_profiles
RootProfile.all
end
def percentage_of_total(answers)
(answers.count.to_f / true_answers.count.to_f) * 100
end
def true_answers
my_quiz.my_answers.where(answer: true)
end
def matching_answers(root_profile)
true_answers
.joins(:questions, :root_profiles)
.where("root_profiles.name = ?", root_profile.name)
end
我不完全理解您正在尝试使用root_branch
方法做什么,因为从我看到的结果来看,它正在返回包含(1) all 数据库中RootProfile
对象的>,以及(2)包含该root_profile
的百分比计数的哈希集合(由root_count
方法返回)。我认为您应该对此重新考虑逻辑。
此外,我可能会考虑将root_profiles
作为实例变量(您也要使用该类初始化(也带有attr_reader
))-因为它将加载整个root_profiles
表,因此最好只调用一次