所以我的视频模型中有这两种方法。第一个采用参数store
并对其进行一些时髦的数学运算以返回rounded_num
。第二种方法应该是通过将rank_sum
的值传递给rounded_num
方法,将数据库中的vote_sum
设置为rank_sum
的值。以下是方法:
def rank_sum(score)
order = Math.log10(([score.abs,1].max))
if score > 0
sign = 1
elsif score < 0
sign = -1
else
sign = 0
end
seconds = self.created_at - DateTime.new(1970,1,1)
long_num = order + sign * seconds / 45000
return rounded_num = (long_num * 10**7).round.to_f / (10**7)
end
def update_rank_sum
new_rank = rank_sum(self.vote_sum)
video.update_attributes!(:rank_sum => new_rank)
end
但是,rank_sum
未设置。每个视频的rank_sum值仍为零。我该如何解决这个问题?
答案 0 :(得分:1)
由于您的rank_sum
方法不直接与Video
模型的实例进行交互(例如一个特定视频),而只是进行一些计算,我会做它是一种类方法。这也使得你的方法不会覆盖Active Record自己的rank_sum
方法,它是根据数据库中的列创建的。
将某些名称更改为更具描述性并清理第一种方法中的return
语句,我会尝试这样的事情:
class Video < ActiveRecord::Base
before_update :update_rank_sum
def self.calculate_rank_sum(score, created_at)
order = Math.log10(([score.abs,1].max))
if score > 0
sign = 1
elsif score < 0
sign = -1
else
sign = 0
end
seconds = created_at - DateTime.new(1970,1,1)
long_num = order + sign * seconds / 45000
(long_num * 10**7).round.to_f / (10**7)
end
def update_rank_sum
self.rank_sum = Video.calculate_rank_sum(self.vote_sum, self.created_at)
end
end
每次保存记录时,这将重新计算rank_sum
列。如果您只想更改某个字段时重新计算它,则可以在update_rank_sum
回调中实现该逻辑。例如,如果rank_sum
已更改,则仅计算新的vote_sum
:
def update_rank_sum
if self.vote_sum_changed?
self.rank_sum = Video.calculate_rank_sum(self.vote_sum, self.created_at)
end
true
end
您可以将vote_sum
中的vote_sum_changed?
替换为您要检查的列。
[编辑]您可能需要在回调中返回非false
或nil
值,以确保记录仍然保存(如果您从before_
回调中返回false,则取消保存)。我已经更新了最后一个代码块。