2015-10-11 2 views
1

В веб-приложении, которое я создаю, я должен вычислить оценку для каждого пользователя. В настоящее время я рассчитываю счет таким образом:Лучший способ суммировать атрибуты с Ruby on Rails

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 

Но у меня такое ощущение, что это не лучший способ это сделать. Есть ли лучший способ сделать это?

ответ

1

Ну, я могу предложить использовать все рубиновый власть в #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 

Другая вещь, которую вы могли бы сделать, это переместить некоторые вычисления в базу данных:

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 

Это просто улучшение производительности, и я не считаю его элегантным.

+0

Спасибо, я использую ваше первое решение :). –

0

Есть несколько улучшений вы могли бы сделать здесь, что я хотел бы пойти на является

Пересчитайте счет, когда атрибуты изменения

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, как оценка рассчитывается в модели пользователя

class User 
    def update_score 
    self.score = self.opinions.sum(:score) 
    end 
end 
Смежные вопросы