2012-04-16 4 views
0

Предположим, у меня есть приложение Rails, которое касается объектов Posts and Comment. A Post has_many Комментарии и каждый Комментарий belongs_to a Post.Использование методов помощников рельсов и контроллеров

В каждом комментарии имеется word_count. Объект Post имеет свойство average_comment_word_count, которое является средним значением каждого из комментариев word_count.

Первый вопрос: если объект Post изменяется асинхронно (комментарии добавляются, что влияет на среднее число слов), в какой момент я должен пересчитать свойство? Когда объект возвращается? Или каждый раз, когда добавляется новый комментарий? Входит ли он в методы комментариев или почтовых помощников? Какая функция контроллера должна вызывать этот метод?

Также, когда я включаю следующий метод почтового помощника, я получаю значение NULL, возвращаемое как JSON.

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
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 %> 

Update: Как @coreward нот, первая часть этого ответа не полезна для asynchrono мы обновляем, но остальная часть ответа может по-прежнему быть полезной.

+0

Это делает много дополнительных запросов * и * он не учитывает асинхронных запросов. – coreyward

+0

@coreyward, хорошая точка в асинхронных запросах, но я не вижу дополнительных запросов. Каждый post.comments.average (: foo) создает одно заявление sql. – Mori

+0

Я считаю, что этот подход проще реализовать (и более общий), чем кеш-счетчик клиентов, поэтому я отмечаю его как принятый. –

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

+0

Я не использую шаблоны просмотра Rails, вместо этого отправляю ответ JSON. Что-нибудь изменит ваш ответ, помимо части просмотров? –

+0

Также я пытаюсь обвести голову вокруг выполнения математических операций с численными свойствами объекта. Подсчет слов - отличное решение IMO, но не общее. Спасибо за ответ, хотя :) –

+0

@AndrewBarinov Я буквально проделал всю работу, просто выведите параметр в своем JSON вместо HTML (JSON - это вид, кстати). Однако я не знаю, что вы делаете о «математических операциях над свойствами числовых объектов». У вас уже есть метод 'word_count' для комментариев в соответствии с вашим сообщением, а' post # words_count' и 'post # comments_count' являются одновременно доступными для числовых столбцов в базе данных. – coreyward

Смежные вопросы