我的几个模型中有以下代码行:
def average(scores)
# get average of scores and round to two decimal places
average = scores.inject{ |sum, el| sum + el }.to_f / scores.size
average.round(2)
end
我试图将它放在各种帮助文件中,并取得了不同的成功 - 但问题不在于我无法工作,而是需要一些丑陋的代码和/或额外的文件(模块等)只是在所有模型中包含此方法 - 这会引发一些危险信号。应该不那么难。
辅助代码对于控制器和视图来说很容易,但对于模型来说似乎是非常直观的 - 与此同时,在4个地方(字面上)完全相同的代码似乎很愚蠢。干这个的最好方法是什么?
更新
我想在每个模型的方法中使用average
帮助器 - 在每种情况下都是不同的,但对于所有内容均为平均值的最后一行 - 如下所示:
def avg_for(student)
scores = []
self.evals.map do |student_id, evals|
evals.select {student_id == student.id}.each do |eval|
scores << eval.score
end
end
average(scores) #here!
end
答案 0 :(得分:2)
http://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-average
class Student < ActiveRecord::Base
has_many :evals
def average_score
evals.average(:score)
end
end
在Rails之外:
def average(score)
(score.inject(:+).to_f / score.size).round(2)
end
修改强>
使用avg_for
方法:
def avg_for(student)
evals.where(student: student).average(:score)
end
答案 1 :(得分:1)
对于这个非常具体的方法,您可以使用@delba answer。
要准确回答有关跨模型共享方法的问题,那就是concern作业。
在rails-4中,关注点成为顶级公民,并自动创建目录app/models/concerns
和app/controllers/concerns
。
您可以在app/concerns/averageable.rb
:
module Averageable
def average(scores)
# get average of scores and round to two decimal places
average = scores.inject{ |sum, el| sum + el }.to_f / scores.size
average.round(2)
end
end
然后,在您的模型中使用它:
class User < ActiveRecord::Base
include Averageable
end
您所关注的方法将适用于包含它的任何模型。
编辑:
要在rails-3中执行相同操作,请将您关注的路径添加到config.autoload_paths
中的config/application.rb
:
config.autoload_paths += %W(#{config.root}/lib/concerns)
将averageable.rb
模块放在该目录中。