我想要计算平均值的组件
控制器
def set_average_course
@course = @group.courses.find(params[:course_id])
@evaluations = @course.evaluations
@evaluations.each do |evaluation|
@numerator += evaluation.average * evaluation.coefficient
@denumerator += evaluation.coefficient
end
@average = @numerator / @denumerator
@course.update(average: average)
end
日志
NoMethodError (undefined method `+' for nil:NilClass)
但是
@numerator += evaluation.average * evaluation.coefficient
在.each块之外定义明确
答案 0 :(得分:1)
使用SQL计算值会更好,更有效:
代码如下所示:
def set_average_course
@course = @group.courses.find(params[:course_id])
res = Evaluation.select("SUM(Evaluations.average * Evaluations.coefficient) AS numerator, SUM(Evaluations.coefficient) AS denumerator").
where(course_id: @course.id)
average = res.first['numerator'] / res.first['denominator'] # Raise an error if 0
@course.update(average: average)
end
希望这能引导你走向正确的方向
答案 1 :(得分:0)
第一次进入each
循环时,@numerator
和@denumerator
尚未初始化。实例变量与局部变量的不同之处在于,如果尚未初始化,则它们将计算为nil
,而对未初始化的局部变量的引用将引发错误。解决方案是在进入循环之前将变量初始化为加法的中性元素,即0
:
def set_average_course
@course = @group.courses.find(params[:course_id])
@evaluations = @course.evaluations
@numerator = 0
@denumerator = 0
@evaluations.each do |evaluation|
@numerator += evaluation.average * evaluation.coefficient
@denumerator += evaluation.coefficient
end
@average = @numerator / @denumerator
@course.update(average: average)
end
虽然,作为旁注,我认为你的意思是"分母"而不是" denumerator"。您还必须考虑@denumerator
等于0
的情况,例如,当@evaluations
为空时:
def set_average_course
@course = @group.courses.find(params[:course_id])
@evaluations = @course.evaluations
return if @evaluations.blank? # or raise an error
@numerator = 0
@denumerator = 0
@evaluations.each do |evaluation|
@numerator += evaluation.average * evaluation.coefficient
@denumerator += evaluation.coefficient
end
@average = @numerator / @denumerator
@course.update(average: average)
end
答案 2 :(得分:0)
尝试将numerator
和denumerator
初始化为@ p11y的回答。
我的建议是计算平均更多红宝石的方式:
@numerator = @evaluations.map { |e| e.average * e.coefficient }.reduce(&:+)
@denumerator = @evaluations.map { |e| e.coefficient }.reduce(&:+)
@average = @numerator / @denumerator