From b63b3a633a6ab2606c3a2f8017a826582cde09ca Mon Sep 17 00:00:00 2001 From: Claudio Ortolina Date: Mon, 2 Dec 2024 10:20:47 +0000 Subject: [PATCH] Can fetch records by a specific artist --- lib/music_library/records.ex | 23 ++++++++++++++++++- lib/music_library/records/artist_records.ex | 16 +++++++++++++ ...41202095949_create_artist_records_view.exs | 18 +++++++++++++++ test/music_library/records_test.exs | 23 +++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 lib/music_library/records/artist_records.ex create mode 100644 priv/repo/migrations/20241202095949_create_artist_records_view.exs diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index 162c0b17..2ceb2b5d 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -6,7 +6,7 @@ defmodule MusicLibrary.Records do import Ecto.Query, warn: false alias MusicLibrary.Repo - alias MusicLibrary.Records.{Cover, Record, SearchParser} + alias MusicLibrary.Records.{ArtistRecord, Cover, Record, SearchParser} def essential_fields do [ @@ -17,6 +17,7 @@ defmodule MusicLibrary.Records do :artists, :genres, :musicbrainz_id, + :purchased_at, :release_ids, :included_release_group_ids, :cover_hash, @@ -89,6 +90,26 @@ defmodule MusicLibrary.Records do def get_record!(id), do: Repo.get!(Record, id) + def get_artist(musicbrainz_id) do + q = + from ar in ArtistRecord, + where: ar.musicbrainz_id == ^musicbrainz_id, + limit: 1, + select: ar.artist + + Repo.one(q) + end + + def get_artist_records(musicbrainz_id) do + q = + from r in Record, + join: ar in ArtistRecord, + on: r.id == ar.record_id and ar.musicbrainz_id == ^musicbrainz_id, + select: ^essential_fields() + + Repo.all(q) + end + def get_cover(id) do q = from r in Record, diff --git a/lib/music_library/records/artist_records.ex b/lib/music_library/records/artist_records.ex new file mode 100644 index 00000000..9e7d52df --- /dev/null +++ b/lib/music_library/records/artist_records.ex @@ -0,0 +1,16 @@ +defmodule MusicLibrary.Records.ArtistRecord do + @moduledoc """ + This is a lookup table that maps from an artist musicbrainz_id to a record id. + """ + use Ecto.Schema + + alias MusicLibrary.Records.Artist + + @primary_key false + schema "artist_records" do + field :musicbrainz_id, Ecto.UUID + field :record_id, Ecto.UUID + + embeds_one :artist, Artist + end +end diff --git a/priv/repo/migrations/20241202095949_create_artist_records_view.exs b/priv/repo/migrations/20241202095949_create_artist_records_view.exs new file mode 100644 index 00000000..6a7d9bf0 --- /dev/null +++ b/priv/repo/migrations/20241202095949_create_artist_records_view.exs @@ -0,0 +1,18 @@ +defmodule MusicLibrary.Repo.Migrations.CreateArtistRecordsView do + use Ecto.Migration + + def up do + execute """ + CREATE VIEW artist_records AS + SELECT json_extract(json_each.value, '$.musicbrainz_id') AS musicbrainz_id, + records.id AS record_id, + json_each.value as artist + FROM records, + json_each(records.artists) + """ + end + + def down do + execute "DROP VIEW artist_records" + end +end diff --git a/test/music_library/records_test.exs b/test/music_library/records_test.exs index 26732880..fdcc5ef2 100644 --- a/test/music_library/records_test.exs +++ b/test/music_library/records_test.exs @@ -156,6 +156,29 @@ defmodule MusicLibrary.RecordsTest do end end + describe "get_artists_records/1" do + test "it returns records with essential data" do + expected = record_fixture() + + artist_musicbrainz_id = expected.artists |> hd() |> Map.get(:musicbrainz_id) + + [artist_record] = Records.get_artist_records(artist_musicbrainz_id) + + assert expected.id == artist_record.id + end + end + + describe "get_artist/1" do + test "it returns records with essential data" do + record = record_fixture() + expected = record.artists |> hd() + + artist = Records.get_artist(expected.musicbrainz_id) + + assert expected == artist + end + end + describe "get_cover/1" do test "it returns the record cover by id" do # while this test may seem redundant, it implicitely checks that ALL record fields are returned,