我不确定这是因为我使用Rails 4但是我很困惑。
I have the following models set:
class Post < ActiveRecord::Base
has_many :stars, :as => :starable, :dependent => :destroy
belongs_to :user
end
class Star < ActiveRecord::Base
before_create :add_to_total_stars
belongs_to :starable, :polymorphic => true
protected
def add_to_total_stars
if [Post].include?(starable.class)
self.starable.update_column(:total_stars, starable.total_stars + self.number)
end
end
end
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :votes, dependent: :destroy
end
所以我在Rails控制台中创建了一个星标和一个帖子:
star = post.stars.build number: 2
post = Post.create title: "test", content: "test", user_id: 1
然后使用以下内容修改average_stars
中的post
列:
star.starable.update(:average_stars, 4)
到目前为止一切正常:
star.starable
=> #<Post id: 9, title: "test", content: "test", created_at: "2013-07-25 16:05:52", updated_at: "2013-07-25 16:05:52", user_id: 1, average_stars: 4, total_stars: 0.0>
但后来我想查看post
,我看到了这个:
post
=> #<Post id: 9, title: "test", content: "test", created_at: "2013-07-25 16:05:52", updated_at: "2013-07-25 16:05:52", user_id: 1, average_stars: 0, total_stars: 0.0>
average_stars
根本没有更新。
为什么update_column更新star.starable而不是帖子?
答案 0 :(得分:2)
这没有错。您的star
和post
对象现在只在内存中。您更改了post
的数据库数据,但内存中的post
对象不会自动重新连接到数据库以更新其内部数据。你必须手动post.reload
做这件事。
根据您的代码的上下文,这可能非常好。
另外,除非你真的,真的,真的想要提高性能,average_stars
不应该是属性/列,而应该是派生的属性,你可以在需要时动态计算。
编辑关于制作派生属性,我的意思是你要为它制作一个方法。目前它是数据库中的一列,因此您可以执行以下操作:
Post.first.average_stars # => 4
而是在average_stars
模型中创建一个名为Post
的方法:
class Post < ActiveRecord::Base
# ...
def average_stars
# calculate
return the_result
end
end
然后你可以像以前一样调用这个方法,但不是从数据库中抓取它,而是计算它。你可以memoize这样,对于你的物体的生命时间它不必重新计算它(除非你强迫它),但要小心。