假设我有一个处理帖子和评论对象的Rails应用程序。发布帖子has_many
评论和每条评论belongs_to
发帖。
每个评论都有word_count
属性。 Post对象具有average_comment_word_count
属性,该属性是每个Comment word_count
的平均值。
第一个问题是,如果Post对象被异步修改(添加的注释会影响平均字数),我应该在什么时候重新计算属性?当对象返回?或者每次添加新评论?它是否会进入评论或发布辅助方法?哪个控制器功能应调用此方法?
当我包含以下Post帮助器方法时,我得到一个返回为JSON的NULL值。
def average_word_count
@average_word_count = 0
# current_user returns the current user object
# user has_many posts and each post belongs_to a user
current_user.posts.find(params[:id]).comments.each do |comment|
@average_word_count += comment.word_count / current_user.posts.find(params[:id]).comments.count
end
@average_word_count
end
答案 0 :(得分:2)
class Comment < ActiveRecord::Base
belongs_to :post
after_save :update_post_word_count
def update_post_word_count
average_wc = post.comments.average(:word_count)
post.update_attributes average_comment_word_count: average_wc
end
end
或者,只在您需要时才获得它:
class Post < ActiveRecord::Base
has_many :comments
def average_comment_word_count
comments.average :word_count
end
end
或者,如果只是在流量较低的地方使用过一次,那就肆无忌惮地藐视得墨忒耳法则,并根据需要从邮政对象中计算出来:
Average Comment Word Count: <%= @post.comments.average :word_count %>
更新:正如@coreward所说,这个答案的第一部分对异步更新没有用,但其余的答案可能仍然有用。
答案 1 :(得分:1)
根据ActiveModel中已有的跟踪单词总数的内容,构建自定义计数器缓存会更好,然后只计算注释以手动进行数学运算。
# you need a comments_count column and a words_count column in this table
class Post < ActiveRecord::Base
has_many :comments
def avg_words_per_comment
words_count / comments_count
end
end
class Comment < ActiveRecord::Base
belongs_to :post, :counter_cache => true
after_save { update_counters(post.id, :words => word_count }
before_destroy { update_counters(post.id, :words => -word_count }
end
# And in your view:
<p>
The average comment for this post has <%= @post.avg_words_per_comment %> words.
</p>
然后你不必担心异步性,并且对视图的计算是最小的。
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/counter_cache.rb#L65