0

假设我有一个处理 Posts 和 Comment 对象的 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
4

2 回答 2

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

或者,如果它只是在流量较低的地方使用过一次,那么就无视得墨忒耳法则,并根据需要从 post 对象中计算它:

Average Comment Word Count: <%= @post.comments.average :word_count %>

更新:正如@coreward 所指出的,这个答案的第一部分对异步更新没有用,但答案的其余部分可能仍然有用。

于 2012-04-16T20:38:34.197 回答
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

于 2012-04-16T21:11:41.367 回答