As @damien pointed out in a comment I needed to change:
has_many :collectionitems, through: :collectable
to:
has_many :collectionitems, as: :collectable
Once this was in place everythign worked as expected.
Thanks again @damien!
質問
So I started to setup a has_many :through polymorphic association in my app. The models look like the following:
class Song < ActiveRecord::Base
has_many :collections, through: :collectionitems
has_many :collectionitems, through: :collectable
end
class Album < ActiveRecord::Base
has_many :collections, through: :collectionitems
has_many :collectionitems, through: :collectable
end
class Collection < ActiveRecord::Base
has_many :albums, through: :collectionitems, source: :collectable, source_type: "Album"
has_many :songs, through: :collectionitems, source: :collectable, source_type: "Song"
has_many :collectionitems
end
class Collectionitem < ActiveRecord::Base
belongs_to :collection
belongs_to :collectable, polymorphic: true
end
This allows me to do the following calls:
Collection.first.songs
=> returns an array of songs for the first collection
Collection.first.albums
=> returns an array of albums for the first collection
Collectionitem.first.collection
=> returns the collection this Collectionitem belongs to
Collectionitem.first.collectable
=> returns the record this Collectionitem belongs to (song or album)
My problem comes when I try to find all the collections a specific album or song belongs to.
both Song.first.collections
and Album.first.collections
return the following error when called in rails console.
Song.first.collections
Song Load (0.2ms) SELECT "songs".* FROM "songs" ORDER BY "songs"."id" ASC LIMIT 1
NoMethodError: undefined method `klass' for nil:NilClass
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:420:in `block in source_reflection'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:420:in `collect'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:420:in `source_reflection'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:579:in `derive_class_name'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:133:in `class_name'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:178:in `klass'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:420:in `block in source_reflection'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:420:in `collect'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:420:in `source_reflection'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/reflection.rb:557:in `check_validity!'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/associations/association.rb:25:in `initialize'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/associations/has_many_through_association.rb:9:in `initialize'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/associations.rb:157:in `new'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/associations.rb:157:in `association'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/associations/builder/association.rb:70:in `collections'
from (irb):3
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in `start'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in `start'
from /Users/jonathan/.rvm/gems/ruby-1.9.3-p392/gems/railties-4.0.0/lib/rails/commands.rb:64:in `<top (required)>'
from bin/rails:4:in `require'
Can someone tell me what i've gotten wrong here. Its as if it doesn't see the songs relationship to the collection? I just don't know what I've done wrong.
解決
As @damien pointed out in a comment I needed to change:
has_many :collectionitems, through: :collectable
to:
has_many :collectionitems, as: :collectable
Once this was in place everythign worked as expected.
Thanks again @damien!