Understanding has_many relations in STI models

Hello everyone! How would I setup a has_many relation between two STI models?

Say I have:

Asset < ApplicationRecord
Song < Asset
Collection < ApplicationRecord
Playlist < Collection.

How would I let Playlist have many songs? In models without the STI I simply did has_and_belongs_to but it doesn’t seem to work with the STI in place. I probably need a join table model but I’m confused on how that should look like

I almost got it to work by having a joint model assets_collection:

class AssetsCollection < ApplicationRecord
  belongs_to :collection, polymorphic: true
  belongs_to :asset, polymorphic: true
end

and then having:

class Playlist < Collection
  has_many :assets_collections, as: :collection
  has_many :songs, through: :assets_collections, source: :asset, source_type: "Song"
end
class Song < Asset
  has_many :assets_collections, as: :asset
  has_many :playlists, through: :assets_collections, source: :collection, source_type: "Playlist"
end

This is the “expanded” method (I usually did playlist.update(songs: Song.find(selected_songs)))

def patch_playlist
    @playlist = Playlist.find(params[:id])
    song_ids = params[:selected_songs]&.map(&:to_i) || []
    songs = Song.where(id: song_ids)
    if song_ids.blank?
      @playlist.songs = []
    else
      @playlist.songs = songs
    end
    if @playlist.save
      redirect_back_or_to collections_path, notice: "Songs added to playlist.", status: :ok
      debugger
    else
      redirect_back_or_to collections_path, alert: "Songs could not be added to playlist." + @playlist.errors.full_messages, status: :unprocessable_entity
    end
  end

When I inspect @playlist.songs (in the debugger inside the method ) I can see the songs inside just fine, assign them to a variable, put their attributes etc. In another method that requests the same playlist, and in the general interactive console though, playlist.songs is always empty. I’m left with some garbage playlist.assets_collections which just have an id and created_at

Ok everyone, the schema was just a bit screwed. I dropped the db and redid the migrations, in the end I got:

class Song < Asset
  has_many :assets_collections
  has_many :playlists, through: :assets_collections, foreign_key: :collection_id
end
class Playlist < Collection
  has_many :assets_collections, as: :collection
  has_many :songs, through: :assets_collections, foreign_key: :asset_id, source: :asset
end

You also need to make sure that the join model assets_collection has asset_id and collection_id and they are the correct type. I have no idea why you need source: in playlist but not in song, but rails threw an error that source was needed in playlist so I added it