RailsCast #154 on Polymorphic Associationに従って、次のように移行をセットアップしました。
# db/migrate/20130719120000_create_comments.rb
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :subject
t.text :message
t.belongs_to :commentable, polymorphic: true
t.timestamps
end
add_index :comments, [:commentable_id, :commentable_type]
end
end
モデルは次のようになります。
# app/models/comment.rb
class Comment < ActiveRecord::Base
attr_accessible :message, :subject
belongs_to :commentable, polymorphic: true
counter_culture :commentable # This does not work, read below.
end
コメントは複数のモデルに設定できます。以下に 1 つの例を示します。
# app/models/product.rb
class Product < ActiveRecord::Base
has_many :comments, as: :commentable
attr_accessible :name
end
これはうまくいきます。
ここで、コメントの数を単純にカウントするgem counter_culture ( Commentモデルでわかるように) も使用します。関連付けられたモデル (この場合はProduct ) のプロパティとしてカウント値を格納します。コメントモデルをポリモーフィズムに切り替える前に、統合は機能していました。
に変更counter_culture :commentable
するcounter_culture :product
と、次のエラー メッセージが表示されます。
NoMethodError: undefined method `product' for #<Comment:0x0000000531cdb0>
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/activemodel-3.2.13/lib/active_model/attribute_methods.rb:407:in `method_missing'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/activerecord-3.2.13/lib/active_record/attribute_methods.rb:149:in `method_missing'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/counter_culture-0.1.12/lib/counter_culture.rb:301:in `foreign_key_value'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/counter_culture-0.1.12/lib/counter_culture.rb:243:in `change_counter_cache'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/counter_culture-0.1.12/lib/counter_culture.rb:196:in `block (2 levels) in _update_counts_after_create'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/counter_culture-0.1.12/lib/counter_culture.rb:194:in `each'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/counter_culture-0.1.12/lib/counter_culture.rb:194:in `block in _update_counts_after_create'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/counter_culture-0.1.12/lib/counter_culture.rb:186:in `call'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/counter_culture-0.1.12/lib/counter_culture.rb:186:in `_wrap_in_counter_culture_active'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/counter_culture-0.1.12/lib/counter_culture.rb:193:in `_update_counts_after_create'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:405:in `_run__2202164684578441182__create__891150410440608527__callbacks'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:405:in `__run_callback'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:385:in `_run_create_callbacks'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/activesupport-3.2.13/lib/active_support/callbacks.rb:81:in `run_callbacks'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/activerecord-3.2.13/lib/active_record/callbacks.rb:268:in `create'
from /home/jjd/.rvm/gems/ruby-1.9.3-p448@demoapp/gems/activerecord-3.2.13/lib/active_record/persistence.rb:348:in `create_or_update'
これは基本的に_update_counts_after_create
192行を指します。
# Source: https://github.com/magnusvk/counter_culture/blob/master/lib/counter_culture.rb#L192
# called by after_create callback
def _update_counts_after_create
_wrap_in_counter_culture_active do
self.class.after_commit_counter_cache.each do |hash|
# increment counter cache
change_counter_cache(hash.merge(:increment => true))
end
end
end
hash
whilecounter_culture :commentable
が設定されていることを調べると、 Productモデル:relation
に解決されていることがわかります。
{:relation=>[:commentable], :counter_cache_name=>"comments_count", :column_names=>nil, :foreign_key_values=>nil}
これは、リレーションが割り当てられている29 行目で行う必要があると思います。
:relation => relation.is_a?(Enumerable) ? relation : [relation],
製品モデルrelation
を解決するためのポリモーフィック アソシエーションであるかどうかをテストするにはどうすればよいですか?