我有一个链接,它是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?
提前致谢!
答案 0 :(得分:1)
创建对象后,after_initialize
回调正确运行。在您的示例中,您正在创建一个新对象,此时累积分数被正确评估为零。之后,您创建一个新注释并重新加载您的Link对象。但是,这不会创建新的Link对象,只是从数据库重新加载它的属性。因此,您对累积分数的原始评估仍然存在。
除了在初始化时计算此值,您应该推迟计算,直到您确实需要它为止。如果您愿意,可以在此时缓存结果。
def cumulative_score
@cumulative_score ||= comments.inject(0) { |sum, comment| sum += comment.score }
end