利用rails helper和controller方法

时间:2012-04-16 20:15:08

标签: ruby-on-rails ruby ruby-on-rails-3.2

假设我有一个处理帖子和评论对象的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

2 个答案:

答案 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