So I have these two methods in my Video model. The first one takes the parameter store and does some funky math to it to return rounded_num. The second method should be setting rank_sum in the database to the value of rounded_num by passing the value of vote_sum to the rank_sum method. Here are the methods:
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
However, rank_sum is not being set. The value for each video’s rank_sum is still nil. How do I fix this?
Since your
rank_summethod doesn’t directly interact with an instance of theVideomodel (e.g. one specific video) and instead simply does some calculation, I would make it a class method. This also makes it so that your method isn’t overwriting Active Record’s ownrank_summethod, which it created based on the columns in your database.Changing some of the names to be more descriptive and cleaning up the
returnstatement in your first method, I would try something like this:This will recalculate the
rank_sumcolumn every time the record is saved. If you only want to recalculate it if a certain field was changed, you can implement that logic in yourupdate_rank_sumcallback. For example, to only calculate a newrank_sumif thevote_sumhas been changed:You can replace
vote_suminvote_sum_changed?with whatever column you want to check.[Edit] You may need to return a non
falseornilvalue in the callback to make sure the record still saves (if you return false from abefore_callback it cancels the save). I’ve updated the last code block.