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