I’m working on a small project where I’m trying to learn how to use embedded schemas. So I have albums and tracks. Album can have many tracks and they are saved in jsonb field using embedded schema. I want to be able to add new tracks and also, delete them.
In create_track() function, first I get existing tracks, then there is a map with a new track and then they both get merged, put into changeset and album get updated.
def create_track(%Album{} = album, attrs \\ %{}) do
existing_tracks = album.tracks
new_track =
%TrackEmbed{
# this is just to show how TrackEmbed looks, real data comes from attrs
name: "track name"
}
tracks = [new_track | existing_tracks]
changeset = Ecto.Changeset.change(album)
changeset
|> Ecto.Changeset.put_embed(:tracks, tracks)
|> Repo.update()
end
To delete a track, I get existing tracks, find a list index where track I want to delete is and then I remove it from the list and the album gets updated.
def delete_track(%Album{} = album, attrs \\ %{}) do
existing_tracks = album.tracks
# real data comes from attrs here too
existing_track_index = Enum.find_index(existing_tracks, fn x -> x.name == "track name" end)
tracks = List.delete_at(existing_tracks, existing_track_index)
changeset = Ecto.Changeset.change(album)
changeset
|> Ecto.Changeset.put_embed(:tracks, tracks)
|> Repo.update()
end
The code I have here works but here I’m getting an existing list and just adding or removing from it, so I was wondering if there is maybe a better way?