Reputation: 725
In a web application I'm currently creating, I have to calculate a score for each user. 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 ?
Upvotes: 1
Views: 70
Reputation: 10592
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
Upvotes: 0
Reputation: 984
Well, I can suggest using all ruby power in #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.
Upvotes: 1