Как реализовать Counter Cache в Rails? - PullRequest
4 голосов
/ 02 июня 2010

У меня есть контроллер сообщений и контроллер комментариев. Пост имеет много комментариев, и комментарии принадлежат посту. Ассоциированный настраивается с включенной опцией counter_cache:

#Inside post.rb
has_many :comments

#Inside comment.rb
belongs_to :post, :counter_cache => true

У меня есть столбец comments_count в моей таблице posts, который по умолчанию равен нулю, как таковой:

add_column :posts, :comments_count, :integer, :default => 0

В действии create моего контроллера комментариев у меня есть следующий код:

def create
  @posts = Post.find(params[:post_id])
  @comment = @post.comments.build(params[:comment])
  if @comment.save
    redirect_to root
  else
    render :action => 'new'
  end
end

Моя проблема: когда вызывается @comment.save, я получаю следующую ошибку:

ArgumentError in CommentsController#create

wrong number of arguments (2 for 0)

Удаление :counter_cache => true из comment.rb полностью решает проблему, поэтому я предполагаю, что это является причиной этой расплывчатой ​​ошибки. Что мне здесь не хватает? Как я могу сохранить свой комментарий и по-прежнему следить за тем, чтобы мой counter_cache заботился о моем сообщении?

Спасибо!


Обновление - трассировка приложения прилагается:

/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:987:in `update_all'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:987:in `update_counters_without_lock'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/locking/optimistic.rb:176:in `update_counters'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:1006:in `increment_counter'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/associations.rb:1367:in `belongs_to_counter_cache_after_create_for_feed_entry'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/callbacks.rb:178:in `send'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/callbacks.rb:178:in `evaluate_method'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/callbacks.rb:166:in `call'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/callbacks.rb:93:in `run'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/callbacks.rb:92:in `each'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/callbacks.rb:92:in `send'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/callbacks.rb:92:in `run'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/callbacks.rb:276:in `run_callbacks'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/callbacks.rb:344:in `callback'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/callbacks.rb:267:in `create'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2915:in `create_or_update_without_callbacks'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/callbacks.rb:250:in `create_or_update'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2573:in `save_without_validation'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/validations.rb:1090:in `save_without_dirty'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/dirty.rb:79:in `save_without_transactions'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:229:in `send'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:229:in `with_transaction_returning_status'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:182:in `transaction'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:228:in `with_transaction_returning_status'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:196:in `save'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:196:in `save'
/Users/yuval/Sites/rails/blog/app/controllers/comments_controller.rb:6:in `create'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/base.rb:1331:in `send'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/base.rb:1331:in `perform_action_without_filters'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/filters.rb:617:in `call_filters'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/filters.rb:610:in `perform_action_without_benchmark'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/core_ext/benchmark.rb:17:in `ms'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/core_ext/benchmark.rb:17:in `ms'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/rescue.rb:160:in `perform_action_without_flash'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/flash.rb:151:in `perform_action'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/base.rb:532:in `send'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/base.rb:532:in `process_without_filters'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/filters.rb:606:in `process'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/base.rb:391:in `process'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/base.rb:386:in `call'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.8/lib/action_controller/routing/route_set.rb:438:in `call'

Обратите внимание, что единственная строка, которая не имеет непосредственного отношения к платформе Rails:

/Users/yuval/Sites/rails/blog/app/controllers/comments_controller.rb:6:in `create'

Строка 6 следующая:

if @comment.save

РЕДАКТИРОВАТЬ 2: @posts / @post - опечатка с моей стороны, когда я пишу упрощенный пример для StackOverflow, мое реальное приложение не содержит ошибок.

Проверяя @comment, кажется, что он полностью действителен - он возвращает именно то, что я ожидал - новый экземпляр комментария с любой информацией, которую я передал ему build. Он взрывается только при вызове метода save.

Спасибо за все предложения. Есть еще идеи?

Ответы [ 3 ]

9 голосов
/ 11 июня 2010

Я пробежал образец приложения с вашим кодом, и у меня все заработало.

Я бы посоветовал отладить немного больше, как предлагает hurikhan77, и посмотреть, является ли это просто проблемой @posts / @post, которую предложил dain.

Кроме того, попробуйте создать в консоли сообщение и комментарий с очень простым содержимым, чтобы увидеть, работает ли оно.

$ ruby script/console

# add whatever fields are necessary to create     
> @p = Post.create(:title => "TestPost1")
  # => #<Post id: 3, ...

# again, add whatever is necessary to create
> @c = @p.comments.create(:comment => "TestComment1")
  # => #<Comment id: 8, ...

> Post.find(:last).comments_count
  # => 1

Посмотри, что тебе это даст.

/ JP

2 голосов
/ 11 июня 2010

ArgumentError in CommentsController # создать

неверное количество аргументов (2 для 0)

Вы получаете эту ошибку, потому что @comment не тот объект, который вы ожидаете. Попробуйте отладить это, вставив:

logger.debug @comment.inspect

Вы увидите что-то неожиданное, и это должно поднять хотя бы бровь. Это должно быть то, что вы присвоили Post.find(...) на @posts, но позже попытались работать с @post.

2 голосов
/ 09 июня 2010

Это может быть совершенно неверно, но вы используете @posts, а затем @post?

...