1

我有一个链接,它是 Rails 中的一个 ActiveRecord 对象,它有很多评论。每条评论都有一个分数。我正在定义一个实例变量@cumulative_score来跟踪所有链接评论的得分总和。这是链接定义:

class Link < ActiveRecord::Base
    has_many :comments

    after_initialize :update_cumulative_score

    def cumulative_score
        @cumulative_score
    end

    def update_cumulative_score
        total = 0
        self.comments.each do |comment|
            total = total + comment.score
            puts "comment.score = #{comment.score}" # for debugging
        end
        @cumulative_score = total
        puts "@cumulative_score = #{@cumulative_score}" # for debugging
    end
end

当我将以下内容输入到 rails 控制台时,我得到了一些奇怪的结果:

> link = Link.create
> link.cumulative_score 
    # returns 0

> comment = Comment.create(score: 20, link:link)
> link.reload

# puts debugging
comment.score = 20
total = 20
@cumulative_score = 20

> link.cumulative_score
    # returns 0, NOT 20!

当 puts 语句显示为 20 时,为什么cumulative_score不将自身更改为 20?

提前致谢!

4

1 回答 1

1

after_initialize创建对象后正确运行回调。在您的示例中,您正在创建一个新对象,此时累积分数被正确评估为零。之后,您创建一个新评论并重新加载您的 Link 对象。但是,这不会创建一个新的 Link 对象,只是从数据库中重新加载它的属性。因此,您对累积分数的原始评估仍然有效。

与其在初始化时计算它,不如将计算推迟到您真正需要它时。如果您愿意,您可以在此时缓存结果。

def cumulative_score
  @cumulative_score ||= comments.inject(0) { |sum, comment| sum += comment.score }
end
于 2013-11-03T22:50:23.550 回答