【问题标题】:Why is my rank_sum database column still nil?为什么我的 rank_sum 数据库列仍然为零?
【发布时间】:2011-03-19 23:06:06
【问题描述】:

所以我的视频模型中有这两种方法。第一个接受参数store 并对其进行一些时髦的数学运算以返回rounded_num。第二种方法应该是通过将vote_sum 的值传递给rank_sum 方法,将数据库中的rank_sum 设置为rounded_num 的值。方法如下:

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 的值仍然为零。我该如何解决这个问题?

【问题讨论】:

  • update_rank_sum 是如何被调用的?
  • 我不这么认为。我认为它可能已被自动调用,但我想这个假设是错误的。我该怎么称呼它?回调?
  • 这就是我需要知道的 :) 请参阅下面的答案。

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


【解决方案1】:

由于您的 rank_sum 方法不直接与 Video 模型的 instance 交互(例如,一个特定的视频),而是简单地进行一些计算,我会将其设为类方法.这也使得您的方法不会覆盖 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 回调中实现该逻辑。例如,如果 vote_sum 已更改,则仅计算新的 rank_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_changed? 中的vote_sum 替换为您要检查的任何列。

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

【讨论】:

  • 一个问题。由于这是在视频模型中,所以在创建和保存视频时,不会只为该视频更新一次 rank_sum 吗?
  • 几分钟前我将答案从before_save 编辑为before_update,这将在每次保存模型时更新列,而不是仅在第一次保存时更新。这是你想要的吗?
  • 不完全。发生的情况是,每当用户投票时,传递给 calculate_rank_sum 的 vote_sum 就会不断变化,所以我想在用户投票时更新 rank_sum。棘手的是投票有自己的模型,VideoVote。
  • 我最新的编辑(见接近尾声)是否会为您处理?
  • 我想是的。如果使用新的 vote_sum 更新视频,这会更新 rank_sum?
猜你喜欢
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-26
相关资源
最近更新 更多