繁体   English   中英

如何干燥此代码?

[英]how to DRY this code?

我的几个模型中都有以下代码行:

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

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

对于这种非常特定的方法,可以使用@delba答案。

要确切回答有关跨模型共享方法的问题,这是一项令人关注的工作。

在rails-4中,关注点成为顶级公民,并自动创建目录app/models/concernsapp/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/application.rb config.autoload_paths添加您要关注的路径:

config.autoload_paths += %W(#{config.root}/lib/concerns)

并将averageable.rb模块放在该目录中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM