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! :-)