Question

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.

Was it helpful?

Solution

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top