为什么我的rank_sum数据库列仍然为零?

时间:2011-03-19 23:06:06

标签: ruby-on-rails ruby database ruby-on-rails-3 model

所以我的视频模型中有这两种方法。第一个采用参数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值仍为零。我该如何解决这个问题?

1 个答案:

答案 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?替换为您要检查的列。

[编辑]您可能需要在回调中返回非falsenil值,以确保记录仍然保存(如果您从before_回调中返回false,则取消保存)。我已经更新了最后一个代码块。