0

I want to use polymorphic association with a model which derives from a base class using single table inheritance (STI). I already investigated further into this problem and (of course) dug through stackoverflow, e.g. here (ActiveRecord, has_many :through, and Polymorphic Associations) and there (ActiveRecord, has_many :through, Polymorphic Associations with STI). Unfortunately all information I found regarded to polymorphic associations but not to the usage in the context of STI.

In my current project I have a design which has one screenshot and many assets linked to it. Some assets (variation assets) should also have screenshots linked to them. Because a design has many assets I want to fetch all screenshots through them.

design.rb

class Design < ActiveRecord::Base
  has_one :screenshot, as: :screenshotable, dependent: :destroy
  has_many :assets, dependent: :destroy
  has_many :screenshots, through: :assets
end

screenshot.rb

class Screenshot < ActiveRecord::Base
  belongs_to :screenshotable, polymorphic: true
end

asset.rb

class Asset < ActiveRecord::Base
  belongs_to :design
end

variation_asset.rb

class VariationAsset < Asset
    # this is the important part as only a
    # variation asset should have a screenshot
    has_one :screenshot, as: :screenshotable, dependent: :destroy
end

Assigning Screenshot to VariationAsset works well. Trying this with Asset raises an NoMethodError as expected (and wanted). Hence the polymorphic interface seems to work and was set up correctly in the schema.

schema.rb

create_table "screenshots", :force => true do |t|
  t.string  "name"
  t.integer "screenshotable_id"
  t.string  "screenshotable_type"
end

create_table "assets", :force => true do |t|
  t.string  "name"
  t.integer "design_id"
  t.string  "type"
end

Querying every Screenshot from a Design through the Asset raises the following error:

active_record/reflection.rb:509:in `check_validity!': Could not find the source association(s) :screenshot or :screenshots in model Asset. Try 'has_many :screenshots, :through => :assets, :source => '. Is it one of :design? (ActiveRecord::HasManyThroughSourceAssociationNotFoundError)

I tried it with the :source parameter as suggested in the error message but this also did not help.

It works when I put the has_one :screenshot, as: :screenshotable, dependent: :destroy line into the STI base class Asset:

class Asset < ActiveRecord::Base
  belongs_to :design
  has_one :screenshot, as: :screenshotable, dependent: :destroy
end

I think it has something to do with the through: parameter and the fact that it seems (for me) to be impossible to tell it to look into VariationAsset instead of Asset somehow.

You find a "working" example of the above code at my github repo.

Any help appreciated! :-)

Community
  • 1
  • 1
Partyschaum
  • 55
  • 1
  • 7
  • Grabbed your repo, but this would all be a *lot* easier with tests/specs. It all runs fine for me, but I have to interpret whether it's supposed to or not. – JohnMetta Jul 22 '13 at 23:33
  • AR will always attempt to get the association information via the base class reflection and not inspect its subclasses. Why would you want to make Asset non-screenshotable in the first place? – Erol Jul 23 '13 at 13:23
  • So what did you specify as :source? It is obvious that AR is confused, because your HATM relation points to :assets, a model which has no :screenshot association in the first place. It would work if you specified :variable_asset there, but then your Design model doesn't have :variable_asset association. Your easiest solution would be adding `has_many :variable_assets` to Design model and using `has_many :screenshots, :through => :variable_assets` instead. – Slava Kravchenko Jul 25 '13 at 11:51

0 Answers0