简体   繁体   English

Ruby on Rails汇总属性的最佳方法

[英]Best way to sum attributes with Ruby on Rails

In a web application I'm currently creating, I have to calculate a score for each user. 在我当前正在创建的Web应用程序中,我必须为每个用户计算一个分数。 I'm currently calculating the score this way : 我目前正在以这种方式计算分数:

class Opinion < ActiveRecord::Base
  belongs_to :hero
  def score_value
    self.note * (self.end_date - self.start_date)
  end
end

class User < ActiveRecord::Base
  has_many :opinions
  def update_score
    self.score = 0
    self.opinions.each { |opinion| self.score += opinion.score_value }
    self.save
  end
end

But I have the feeling that's not the best way to do it. 但是我觉得这不是最好的方法。 Is there any better way to do it ? 有什么更好的办法吗?

Well, I can suggest using all ruby power in #update_score : 好吧,我建议在#update_score使用所有的红宝石功能:

class User < ActiveRecord::Base
  has_many :opinions
  def update_score
    self.score = self.opinions.map(&:score_value).inject(0, &:+)
    self.save
  end
end

Another thing you could do is to move some calculation to database: 您可以做的另一件事是将一些计算移至数据库:

class User < ActiveRecord::Base
  has_many :opinions
  def update_score
    self.score = opinions.pluck(:note, 'DATEDIFF(end_date, start_date)').map do |note, days|
      note * days 
    end.inject(0, &:+)
    self.save
  end
end

This is just a perfomance improvement and I don't think its elegant. 这只是性能上的改进,我认为它并不优雅。

There are multiple improvements you could make here, what I would go for is 您可以在此处进行多项改进,我要做的是

Recalculate the score when attributes are changes 属性更改时重新计算分数

class Opinion
  before_save :update_score

  def update_score
    return unless note_changed? || end_date_changed? || start_date_changed?
    self.note * (self.end_date - self.start_date)
  end
end

Update how score is calculated in User model 更新用户模型中分数的计算方式

class User
  def update_score
    self.score = self.opinions.sum(:score)
  end
end

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

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