实例ActiveRecord对象的变量不随方法调用而改变

时间:2013-11-03 22:28:09

标签: ruby-on-rails ruby ruby-on-rails-4 rails-activerecord

我有一个链接,它是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?

提前致谢!

1 个答案:

答案 0 :(得分:1)

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

除了在初始化时计算此值,您应该推迟计算,直到您确实需要它为止。如果您愿意,可以在此时缓存结果。

def cumulative_score
  @cumulative_score ||= comments.inject(0) { |sum, comment| sum += comment.score }
end