Browse Source

first working version

master
Inhji Y. 2 years ago
parent
commit
e7fc12f8fb
  1. 4
      lib/dagon/application.ex
  2. 104
      lib/dagon/listens/albums.ex
  3. 25
      lib/dagon/listens/albums/album.ex
  4. 104
      lib/dagon/listens/artists.ex
  5. 25
      lib/dagon/listens/artists/artist.ex
  6. 104
      lib/dagon/listens/listens.ex
  7. 21
      lib/dagon/listens/listens/listen.ex
  8. 104
      lib/dagon/listens/tracks.ex
  9. 22
      lib/dagon/listens/tracks/track.ex
  10. 187
      lib/dagon/listens/workers/listenbrainz_worker.ex
  11. 62
      lib/dagon_web/controllers/album_controller.ex
  12. 62
      lib/dagon_web/controllers/artist_controller.ex
  13. 62
      lib/dagon_web/controllers/listen_controller.ex
  14. 62
      lib/dagon_web/controllers/track_controller.ex
  15. 5
      lib/dagon_web/router.ex
  16. 5
      lib/dagon_web/templates/album/edit.html.eex
  17. 23
      lib/dagon_web/templates/album/form.html.eex
  18. 30
      lib/dagon_web/templates/album/index.html.eex
  19. 5
      lib/dagon_web/templates/album/new.html.eex
  20. 23
      lib/dagon_web/templates/album/show.html.eex
  21. 5
      lib/dagon_web/templates/artist/edit.html.eex
  22. 19
      lib/dagon_web/templates/artist/form.html.eex
  23. 28
      lib/dagon_web/templates/artist/index.html.eex
  24. 5
      lib/dagon_web/templates/artist/new.html.eex
  25. 18
      lib/dagon_web/templates/artist/show.html.eex
  26. 5
      lib/dagon_web/templates/listen/edit.html.eex
  27. 11
      lib/dagon_web/templates/listen/form.html.eex
  28. 24
      lib/dagon_web/templates/listen/index.html.eex
  29. 5
      lib/dagon_web/templates/listen/new.html.eex
  30. 8
      lib/dagon_web/templates/listen/show.html.eex
  31. 5
      lib/dagon_web/templates/track/edit.html.eex
  32. 15
      lib/dagon_web/templates/track/form.html.eex
  33. 26
      lib/dagon_web/templates/track/index.html.eex
  34. 5
      lib/dagon_web/templates/track/new.html.eex
  35. 13
      lib/dagon_web/templates/track/show.html.eex
  36. 3
      lib/dagon_web/views/album_view.ex
  37. 3
      lib/dagon_web/views/artist_view.ex
  38. 3
      lib/dagon_web/views/listen_view.ex
  39. 3
      lib/dagon_web/views/track_view.ex
  40. 14
      mix.exs
  41. 10
      mix.lock
  42. 16
      priv/repo/migrations/20191023181552_create_artists.exs
  43. 19
      priv/repo/migrations/20191023205308_create_albums.exs
  44. 16
      priv/repo/migrations/20191023205531_create_tracks.exs
  45. 18
      priv/repo/migrations/20191023205705_create_listens.exs
  46. 68
      test/dagon/listens/albums_test.exs
  47. 66
      test/dagon/listens/artists_test.exs
  48. 62
      test/dagon/listens/listens_test.exs
  49. 64
      test/dagon/listens/tracks_test.exs
  50. 88
      test/dagon_web/controllers/album_controller_test.exs
  51. 88
      test/dagon_web/controllers/artist_controller_test.exs
  52. 88
      test/dagon_web/controllers/listen_controller_test.exs
  53. 88
      test/dagon_web/controllers/track_controller_test.exs

4
lib/dagon/application.ex

@ -11,9 +11,9 @@ defmodule Dagon.Application do
# Start the Ecto repository
Dagon.Repo,
# Start the endpoint when the application starts
DagonWeb.Endpoint
DagonWeb.Endpoint,
# Starts a worker by calling: Dagon.Worker.start_link(arg)
# {Dagon.Worker, arg},
{Dagon.Listens.Workers.ListenbrainzWorker, %{}}
]
# See https://hexdocs.pm/elixir/Supervisor.html

104
lib/dagon/listens/albums.ex

@ -0,0 +1,104 @@
defmodule Dagon.Listens.Albums do
@moduledoc """
The Listens.Albums context.
"""
import Ecto.Query, warn: false
alias Dagon.Repo
alias Dagon.Listens.Albums.Album
@doc """
Returns the list of albums.
## Examples
iex> list_albums()
[%Album{}, ...]
"""
def list_albums do
Repo.all(Album)
end
@doc """
Gets a single album.
Raises `Ecto.NoResultsError` if the Album does not exist.
## Examples
iex> get_album!(123)
%Album{}
iex> get_album!(456)
** (Ecto.NoResultsError)
"""
def get_album!(id), do: Repo.get!(Album, id)
@doc """
Creates a album.
## Examples
iex> create_album(%{field: value})
{:ok, %Album{}}
iex> create_album(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_album(attrs \\ %{}) do
%Album{}
|> Album.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a album.
## Examples
iex> update_album(album, %{field: new_value})
{:ok, %Album{}}
iex> update_album(album, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_album(%Album{} = album, attrs) do
album
|> Album.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a Album.
## Examples
iex> delete_album(album)
{:ok, %Album{}}
iex> delete_album(album)
{:error, %Ecto.Changeset{}}
"""
def delete_album(%Album{} = album) do
Repo.delete(album)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking album changes.
## Examples
iex> change_album(album)
%Ecto.Changeset{source: %Album{}}
"""
def change_album(%Album{} = album) do
Album.changeset(album, %{})
end
end

25
lib/dagon/listens/albums/album.ex

@ -0,0 +1,25 @@
defmodule Dagon.Listens.Albums.Album do
use Ecto.Schema
import Ecto.Changeset
schema "albums" do
field :name, :string
field :slug, :string
field :mbid, :string
field :msid, :string
belongs_to :artist, Dagon.Listens.Artists.Artist
has_many :tracks, Dagon.Listens.Tracks.Track
has_many :listens, Dagon.Listens.Listens.Listen
timestamps()
end
@doc false
def changeset(album, attrs) do
album
|> cast(attrs, [:name, :slug, :mbid, :msid, :artist_id])
|> validate_required([:name, :slug, :msid, :artist_id])
end
end

104
lib/dagon/listens/artists.ex

@ -0,0 +1,104 @@
defmodule Dagon.Listens.Artists do
@moduledoc """
The Listens.Artists context.
"""
import Ecto.Query, warn: false
alias Dagon.Repo
alias Dagon.Listens.Artists.Artist
@doc """
Returns the list of artists.
## Examples
iex> list_artists()
[%Artist{}, ...]
"""
def list_artists do
Repo.all(Artist)
end
@doc """
Gets a single artist.
Raises `Ecto.NoResultsError` if the Artist does not exist.
## Examples
iex> get_artist!(123)
%Artist{}
iex> get_artist!(456)
** (Ecto.NoResultsError)
"""
def get_artist!(id), do: Repo.get!(Artist, id)
@doc """
Creates a artist.
## Examples
iex> create_artist(%{field: value})
{:ok, %Artist{}}
iex> create_artist(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_artist(attrs \\ %{}) do
%Artist{}
|> Artist.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a artist.
## Examples
iex> update_artist(artist, %{field: new_value})
{:ok, %Artist{}}
iex> update_artist(artist, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_artist(%Artist{} = artist, attrs) do
artist
|> Artist.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a Artist.
## Examples
iex> delete_artist(artist)
{:ok, %Artist{}}
iex> delete_artist(artist)
{:error, %Ecto.Changeset{}}
"""
def delete_artist(%Artist{} = artist) do
Repo.delete(artist)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking artist changes.
## Examples
iex> change_artist(artist)
%Ecto.Changeset{source: %Artist{}}
"""
def change_artist(%Artist{} = artist) do
Artist.changeset(artist, %{})
end
end

25
lib/dagon/listens/artists/artist.ex

@ -0,0 +1,25 @@
defmodule Dagon.Listens.Artists.Artist do
use Ecto.Schema
import Ecto.Changeset
schema "artists" do
field :name, :string
field :slug, :string
field :msid, :string
field :mbid, :string
has_many :albums, Dagon.Listens.Albums.Album
has_many :tracks, Dagon.Listens.Tracks.Track
has_many :listens, Dagon.Listens.Listens.Listen
timestamps()
end
@doc false
def changeset(artist, attrs) do
artist
|> cast(attrs, [:name, :slug, :msid, :mbid])
|> validate_required([:name, :msid])
end
end

104
lib/dagon/listens/listens.ex

@ -0,0 +1,104 @@
defmodule Dagon.Listens.Listens do
@moduledoc """
The Listens.Listens context.
"""
import Ecto.Query, warn: false
alias Dagon.Repo
alias Dagon.Listens.Listens.Listen
@doc """
Returns the list of listens.
## Examples
iex> list_listens()
[%Listen{}, ...]
"""
def list_listens do
Repo.all(Listen)
end
@doc """
Gets a single listen.
Raises `Ecto.NoResultsError` if the Listen does not exist.
## Examples
iex> get_listen!(123)
%Listen{}
iex> get_listen!(456)
** (Ecto.NoResultsError)
"""
def get_listen!(id), do: Repo.get!(Listen, id)
@doc """
Creates a listen.
## Examples
iex> create_listen(%{field: value})
{:ok, %Listen{}}
iex> create_listen(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_listen(attrs \\ %{}) do
%Listen{}
|> Listen.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a listen.
## Examples
iex> update_listen(listen, %{field: new_value})
{:ok, %Listen{}}
iex> update_listen(listen, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_listen(%Listen{} = listen, attrs) do
listen
|> Listen.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a Listen.
## Examples
iex> delete_listen(listen)
{:ok, %Listen{}}
iex> delete_listen(listen)
{:error, %Ecto.Changeset{}}
"""
def delete_listen(%Listen{} = listen) do
Repo.delete(listen)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking listen changes.
## Examples
iex> change_listen(listen)
%Ecto.Changeset{source: %Listen{}}
"""
def change_listen(%Listen{} = listen) do
Listen.changeset(listen, %{})
end
end

21
lib/dagon/listens/listens/listen.ex

@ -0,0 +1,21 @@
defmodule Dagon.Listens.Listens.Listen do
use Ecto.Schema
import Ecto.Changeset
schema "listens" do
field :listened_at, :utc_datetime
belongs_to :track, Dagon.Listens.Tracks.Track
belongs_to :artist, Dagon.Listens.Artists.Artist
belongs_to :album, Dagon.Listens.Albums.Album
timestamps()
end
@doc false
def changeset(listen, attrs) do
listen
|> cast(attrs, [:track_id, :album_id, :artist_id, :listened_at])
|> validate_required([:track_id, :album_id, :artist_id, :listened_at])
end
end

104
lib/dagon/listens/tracks.ex

@ -0,0 +1,104 @@
defmodule Dagon.Listens.Tracks do
@moduledoc """
The Listens.Tracks context.
"""
import Ecto.Query, warn: false
alias Dagon.Repo
alias Dagon.Listens.Tracks.Track
@doc """
Returns the list of tracks.
## Examples
iex> list_tracks()
[%Track{}, ...]
"""
def list_tracks do
Repo.all(Track)
end
@doc """
Gets a single track.
Raises `Ecto.NoResultsError` if the Track does not exist.
## Examples
iex> get_track!(123)
%Track{}
iex> get_track!(456)
** (Ecto.NoResultsError)
"""
def get_track!(id), do: Repo.get!(Track, id)
@doc """
Creates a track.
## Examples
iex> create_track(%{field: value})
{:ok, %Track{}}
iex> create_track(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_track(attrs \\ %{}) do
%Track{}
|> Track.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a track.
## Examples
iex> update_track(track, %{field: new_value})
{:ok, %Track{}}
iex> update_track(track, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_track(%Track{} = track, attrs) do
track
|> Track.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a Track.
## Examples
iex> delete_track(track)
{:ok, %Track{}}
iex> delete_track(track)
{:error, %Ecto.Changeset{}}
"""
def delete_track(%Track{} = track) do
Repo.delete(track)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking track changes.
## Examples
iex> change_track(track)
%Ecto.Changeset{source: %Track{}}
"""
def change_track(%Track{} = track) do
Track.changeset(track, %{})
end
end

22
lib/dagon/listens/tracks/track.ex

@ -0,0 +1,22 @@
defmodule Dagon.Listens.Tracks.Track do
use Ecto.Schema
import Ecto.Changeset
schema "tracks" do
field :name, :string
belongs_to :album, Dagon.Listens.Albums.Album
belongs_to :artist, Dagon.Listens.Artists.Artist
has_many :listens, Dagon.Listens.Listens.Listen
timestamps()
end
@doc false
def changeset(track, attrs) do
track
|> cast(attrs, [:name, :album_id, :artist_id])
|> validate_required([:name, :album_id, :artist_id])
end
end

187
lib/dagon/listens/workers/listenbrainz_worker.ex

@ -0,0 +1,187 @@
defmodule Dagon.Listens.Workers.ListenbrainzWorker do
use GenServer
require Logger
import Ecto.Query
alias Dagon.Repo
alias Dagon.Listens.Artists.Artist
alias Dagon.Listens.Albums.Album
alias Dagon.Listens.Tracks.Track
alias Dagon.Listens.Listens.Listen
# 2 Minutes
@fetch_interval 2 * 60 * 1_000
@base_url "https://api.listenbrainz.org/1/user"
def start_link(args) do
Logger.info("Starting Listenbrainz Worker..")
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def update() do
GenServer.cast(__MODULE__, :update)
end
def init(state \\ %{}) do
schedule_fetch(10_000)
{:ok, state}
end
def handle_info(:fetch, state) do
new_state = do_fetch(state)
{:noreply, new_state}
end
def schedule_fetch(wait_time \\ @fetch_interval) do
Logger.info("Scheduling Listenbrainz Worker..")
Process.send_after(self(), :fetch, wait_time)
end
def do_fetch(state) do
last_ts = last_listen_timestamp()
user = "inhji"
url = "#{@base_url}/#{user}/listens?min_ts=#{last_ts}"
Logger.info("Last listen timestamp: #{last_ts}")
Logger.info("Fetching new Listens..")
Logger.info(url)
listens =
case HTTPoison.get!(url) do
%HTTPoison.Response{body: body} ->
body
|> Jason.decode!(keys: :atoms)
|> Map.get(:payload)
|> Map.get(:listens)
_ ->
nil
end
listens
|> prepare_listens()
|> Enum.filter(fn l -> !is_nil(l) end)
|> Enum.each(fn changeset ->
result = Repo.insert(changeset)
Logger.debug(inspect(result))
end)
schedule_fetch()
state
end
def last_listen_timestamp do
case Repo.one(
from l in Dagon.Listens.Listens.Listen,
order_by: [desc: l.listened_at],
limit: 1
) do
nil -> 1
listen -> DateTime.to_unix(listen.listened_at)
end
end
def prepare_listens(listens) do
Enum.map(listens, &prepare_listen/1)
end
def prepare_listen(listen) do
meta = listen.track_metadata
info = meta.additional_info
with {:ok, artist} <- maybe_create_artist(meta.artist_name, info.artist_msid),
{:ok, album} <- maybe_create_album(meta.release_name, info.release_msid, artist),
{:ok, track} <- maybe_create_track(meta.track_name, artist, album) do
Logger.info("Creating new Listen: #{meta.track_name} - #{meta.artist_name}")
Listen.changeset(%Listen{}, %{
track: listen.track_metadata.track_name,
album_id: album.id,
artist_id: artist.id,
track_id: track.id,
listened_at: DateTime.from_unix!(listen.listened_at)
})
else
{:error, reason} ->
Logger.error(inspect(reason))
nil
end
end
def maybe_create_artist(nil, _) do
{:error, "Artist name was nil, skipping."}
end
def maybe_create_artist(name, messybrainz_id) do
artist =
case Repo.get_by(Artist, msid: messybrainz_id) do
nil ->
Logger.info("Creating new artist #{name}")
%Artist{}
|> Artist.changeset(%{
name: name,
slug: Slugger.slugify_downcase(name),
msid: messybrainz_id
})
|> Repo.insert!()
artist ->
artist
end
{:ok, artist}
end
def maybe_create_album(nil, _, _) do
{:error, "Album name was nil, skipping."}
end
def maybe_create_album(name, messybrainz_id, artist) do
album =
case Repo.get_by(Album, name: name) do
nil ->
Logger.info("Creating new album #{name}")
%Album{}
|> Album.changeset(%{
name: name,
slug: Slugger.slugify_downcase(name),
msid: messybrainz_id,
artist_id: artist.id
})
|> Repo.insert!()
album ->
album
end
{:ok, album}
end
def maybe_create_track(name, artist, album) do
track =
Track
|> Repo.get_by(name: name, artist_id: artist.id, album_id: album.id)
|> Repo.preload([:album, :artist])
track =
case track do
nil ->
Logger.info("Creating new track #{name}")
%Track{}
|> Track.changeset(%{
name: name,
artist_id: artist.id,
album_id: album.id
})
|> Repo.insert!()
track ->
track
end
{:ok, track}
end
end

62
lib/dagon_web/controllers/album_controller.ex

@ -0,0 +1,62 @@
defmodule DagonWeb.AlbumController do
use DagonWeb, :controller
alias Dagon.Listens.Albums
alias Dagon.Listens.Albums.Album
def index(conn, _params) do
albums = Albums.list_albums()
render(conn, "index.html", albums: albums)
end
def new(conn, _params) do
changeset = Albums.change_album(%Album{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"album" => album_params}) do
case Albums.create_album(album_params) do
{:ok, album} ->
conn
|> put_flash(:info, "Album created successfully.")
|> redirect(to: Routes.album_path(conn, :show, album))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
album = Albums.get_album!(id)
render(conn, "show.html", album: album)
end
def edit(conn, %{"id" => id}) do
album = Albums.get_album!(id)
changeset = Albums.change_album(album)
render(conn, "edit.html", album: album, changeset: changeset)
end
def update(conn, %{"id" => id, "album" => album_params}) do
album = Albums.get_album!(id)
case Albums.update_album(album, album_params) do
{:ok, album} ->
conn
|> put_flash(:info, "Album updated successfully.")
|> redirect(to: Routes.album_path(conn, :show, album))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "edit.html", album: album, changeset: changeset)
end
end
def delete(conn, %{"id" => id}) do
album = Albums.get_album!(id)
{:ok, _album} = Albums.delete_album(album)
conn
|> put_flash(:info, "Album deleted successfully.")
|> redirect(to: Routes.album_path(conn, :index))
end
end

62
lib/dagon_web/controllers/artist_controller.ex

@ -0,0 +1,62 @@
defmodule DagonWeb.ArtistController do
use DagonWeb, :controller
alias Dagon.Listens.Artists
alias Dagon.Listens.Artists.Artist
def index(conn, _params) do
artists = Artists.list_artists()
render(conn, "index.html", artists: artists)
end
def new(conn, _params) do
changeset = Artists.change_artist(%Artist{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"artist" => artist_params}) do
case Artists.create_artist(artist_params) do
{:ok, artist} ->
conn
|> put_flash(:info, "Artist created successfully.")
|> redirect(to: Routes.artist_path(conn, :show, artist))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
artist = Artists.get_artist!(id)
render(conn, "show.html", artist: artist)
end
def edit(conn, %{"id" => id}) do
artist = Artists.get_artist!(id)
changeset = Artists.change_artist(artist)
render(conn, "edit.html", artist: artist, changeset: changeset)
end
def update(conn, %{"id" => id, "artist" => artist_params}) do
artist = Artists.get_artist!(id)
case Artists.update_artist(artist, artist_params) do
{:ok, artist} ->
conn
|> put_flash(:info, "Artist updated successfully.")
|> redirect(to: Routes.artist_path(conn, :show, artist))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "edit.html", artist: artist, changeset: changeset)
end
end
def delete(conn, %{"id" => id}) do
artist = Artists.get_artist!(id)
{:ok, _artist} = Artists.delete_artist(artist)
conn
|> put_flash(:info, "Artist deleted successfully.")
|> redirect(to: Routes.artist_path(conn, :index))
end
end

62
lib/dagon_web/controllers/listen_controller.ex

@ -0,0 +1,62 @@
defmodule DagonWeb.ListenController do
use DagonWeb, :controller
alias Dagon.Listens.Listens
alias Dagon.Listens.Listens.Listen
def index(conn, _params) do
listens = Listens.list_listens()
render(conn, "index.html", listens: listens)
end
def new(conn, _params) do
changeset = Listens.change_listen(%Listen{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"listen" => listen_params}) do
case Listens.create_listen(listen_params) do
{:ok, listen} ->
conn
|> put_flash(:info, "Listen created successfully.")
|> redirect(to: Routes.listen_path(conn, :show, listen))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
listen = Listens.get_listen!(id)
render(conn, "show.html", listen: listen)
end
def edit(conn, %{"id" => id}) do
listen = Listens.get_listen!(id)
changeset = Listens.change_listen(listen)
render(conn, "edit.html", listen: listen, changeset: changeset)
end
def update(conn, %{"id" => id, "listen" => listen_params}) do
listen = Listens.get_listen!(id)
case Listens.update_listen(listen, listen_params) do
{:ok, listen} ->
conn
|> put_flash(:info, "Listen updated successfully.")
|> redirect(to: Routes.listen_path(conn, :show, listen))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "edit.html", listen: listen, changeset: changeset)
end
end
def delete(conn, %{"id" => id}) do
listen = Listens.get_listen!(id)
{:ok, _listen} = Listens.delete_listen(listen)
conn
|> put_flash(:info, "Listen deleted successfully.")
|> redirect(to: Routes.listen_path(conn, :index))
end
end

62
lib/dagon_web/controllers/track_controller.ex

@ -0,0 +1,62 @@
defmodule DagonWeb.TrackController do
use DagonWeb, :controller
alias Dagon.Listens.Tracks
alias Dagon.Listens.Tracks.Track
def index(conn, _params) do
tracks = Tracks.list_tracks()
render(conn, "index.html", tracks: tracks)
end
def new(conn, _params) do
changeset = Tracks.change_track(%Track{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"track" => track_params}) do
case Tracks.create_track(track_params) do
{:ok, track} ->
conn
|> put_flash(:info, "Track created successfully.")
|> redirect(to: Routes.track_path(conn, :show, track))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
track = Tracks.get_track!(id)
render(conn, "show.html", track: track)
end
def edit(conn, %{"id" => id}) do
track = Tracks.get_track!(id)
changeset = Tracks.change_track(track)
render(conn, "edit.html", track: track, changeset: changeset)
end
def update(conn, %{"id" => id, "track" => track_params}) do
track = Tracks.get_track!(id)
case Tracks.update_track(track, track_params) do
{:ok, track} ->
conn
|> put_flash(:info, "Track updated successfully.")
|> redirect(to: Routes.track_path(conn, :show, track))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "edit.html", track: track, changeset: changeset)
end
end
def delete(conn, %{"id" => id}) do
track = Tracks.get_track!(id)
{:ok, _track} = Tracks.delete_track(track)
conn
|> put_flash(:info, "Track deleted successfully.")
|> redirect(to: Routes.track_path(conn, :index))
end
end

5
lib/dagon_web/router.ex

@ -17,6 +17,11 @@ defmodule DagonWeb.Router do
pipe_through :browser
get "/", PageController, :index
resources "/artists", ArtistController
resources "/albums", AlbumController
resources "/tracks", TrackController
resources "/listens", ListenController
end
# Other scopes may use custom stacks.

5
lib/dagon_web/templates/album/edit.html.eex

@ -0,0 +1,5 @@
<h1>Edit Album</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.album_path(@conn, :update, @album)) %>
<span><%= link "Back", to: Routes.album_path(@conn, :index) %></span>

23
lib/dagon_web/templates/album/form.html.eex

@ -0,0 +1,23 @@
<%= form_for @changeset, @action, fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= error_tag f, :name %>
<%= label f, :slug %>
<%= text_input f, :slug %>
<%= error_tag f, :slug %>
<%= label f, :mbid %>
<%= text_input f, :mbid %>
<%= error_tag f, :mbid %>
<div>
<%= submit "Save" %>
</div>
<% end %>

30
lib/dagon_web/templates/album/index.html.eex

@ -0,0 +1,30 @@
<h1>Listing Albums</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Slug</th>
<th>Mbid</th>
<th></th>
</tr>
</thead>
<tbody>
<%= for album <- @albums do %>
<tr>
<td><%= album.name %></td>
<td><%= album.slug %></td>
<td><%= album.mbid %></td>
<td>
<span><%= link "Show", to: Routes.album_path(@conn, :show, album) %></span>
<span><%= link "Edit", to: Routes.album_path(@conn, :edit, album) %></span>
<span><%= link "Delete", to: Routes.album_path(@conn, :delete, album), method: :delete, data: [confirm: "Are you sure?"] %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= link "New Album", to: Routes.album_path(@conn, :new) %></span>

5
lib/dagon_web/templates/album/new.html.eex

@ -0,0 +1,5 @@
<h1>New Album</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.album_path(@conn, :create)) %>
<span><%= link "Back", to: Routes.album_path(@conn, :index) %></span>

23
lib/dagon_web/templates/album/show.html.eex

@ -0,0 +1,23 @@
<h1>Show Album</h1>
<ul>
<li>
<strong>Name:</strong>
<%= @album.name %>
</li>
<li>
<strong>Slug:</strong>
<%= @album.slug %>
</li>
<li>
<strong>Mbid:</strong>
<%= @album.mbid %>
</li>
</ul>
<span><%= link "Edit", to: Routes.album_path(@conn, :edit, @album) %></span>
<span><%= link "Back", to: Routes.album_path(@conn, :index) %></span>

5
lib/dagon_web/templates/artist/edit.html.eex

@ -0,0 +1,5 @@
<h1>Edit Artist</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.artist_path(@conn, :update, @artist)) %>
<span><%= link "Back", to: Routes.artist_path(@conn, :index) %></span>

19
lib/dagon_web/templates/artist/form.html.eex

@ -0,0 +1,19 @@
<%= form_for @changeset, @action, fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= error_tag f, :name %>
<%= label f, :slug %>
<%= text_input f, :slug %>
<%= error_tag f, :slug %>
<div>
<%= submit "Save" %>
</div>
<% end %>

28
lib/dagon_web/templates/artist/index.html.eex

@ -0,0 +1,28 @@
<h1>Listing Artists</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Slug</th>
<th></th>
</tr>
</thead>
<tbody>
<%= for artist <- @artists do %>
<tr>
<td><%= artist.name %></td>
<td><%= artist.slug %></td>
<td>
<span><%= link "Show", to: Routes.artist_path(@conn, :show, artist) %></span>
<span><%= link "Edit", to: Routes.artist_path(@conn, :edit, artist) %></span>
<span><%= link "Delete", to: Routes.artist_path(@conn, :delete, artist), method: :delete, data: [confirm: "Are you sure?"] %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= link "New Artist", to: Routes.artist_path(@conn, :new) %></span>

5
lib/dagon_web/templates/artist/new.html.eex

@ -0,0 +1,5 @@
<h1>New Artist</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.artist_path(@conn, :create)) %>
<span><%= link "Back", to: Routes.artist_path(@conn, :index) %></span>

18
lib/dagon_web/templates/artist/show.html.eex

@ -0,0 +1,18 @@
<h1>Show Artist</h1>
<ul>
<li>
<strong>Name:</strong>
<%= @artist.name %>
</li>
<li>
<strong>Slug:</strong>
<%= @artist.slug %>
</li>
</ul>
<span><%= link "Edit", to: Routes.artist_path(@conn, :edit, @artist) %></span>
<span><%= link "Back", to: Routes.artist_path(@conn, :index) %></span>

5
lib/dagon_web/templates/listen/edit.html.eex

@ -0,0 +1,5 @@
<h1>Edit Listen</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.listen_path(@conn, :update, @listen)) %>
<span><%= link "Back", to: Routes.listen_path(@conn, :index) %></span>

11
lib/dagon_web/templates/listen/form.html.eex

@ -0,0 +1,11 @@
<%= form_for @changeset, @action, fn _f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<div>
<%= submit "Save" %>
</div>
<% end %>

24
lib/dagon_web/templates/listen/index.html.eex

@ -0,0 +1,24 @@
<h1>Listing Listens</h1>
<table>
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody>
<%= for listen <- @listens do %>
<tr>
<td>
<span><%= link "Show", to: Routes.listen_path(@conn, :show, listen) %></span>
<span><%= link "Edit", to: Routes.listen_path(@conn, :edit, listen) %></span>
<span><%= link "Delete", to: Routes.listen_path(@conn, :delete, listen), method: :delete, data: [confirm: "Are you sure?"] %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= link "New Listen", to: Routes.listen_path(@conn, :new) %></span>

5
lib/dagon_web/templates/listen/new.html.eex

@ -0,0 +1,5 @@
<h1>New Listen</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.listen_path(@conn, :create)) %>
<span><%= link "Back", to: Routes.listen_path(@conn, :index) %></span>

8
lib/dagon_web/templates/listen/show.html.eex

@ -0,0 +1,8 @@
<h1>Show Listen</h1>
<ul>
</ul>
<span><%= link "Edit", to: Routes.listen_path(@conn, :edit, @listen) %></span>
<span><%= link "Back", to: Routes.listen_path(@conn, :index) %></span>

5
lib/dagon_web/templates/track/edit.html.eex

@ -0,0 +1,5 @@
<h1>Edit Track</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.track_path(@conn, :update, @track)) %>
<span><%= link "Back", to: Routes.track_path(@conn, :index) %></span>

15
lib/dagon_web/templates/track/form.html.eex

@ -0,0 +1,15 @@
<%= form_for @changeset, @action, fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= error_tag f, :name %>
<div>
<%= submit "Save" %>
</div>
<% end %>

26
lib/dagon_web/templates/track/index.html.eex

@ -0,0 +1,26 @@
<h1>Listing Tracks</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
<%= for track <- @tracks do %>
<tr>
<td><%= track.name %></td>
<td>
<span><%= link "Show", to: Routes.track_path(@conn, :show, track) %></span>
<span><%= link "Edit", to: Routes.track_path(@conn, :edit, track) %></span>
<span><%= link "Delete", to: Routes.track_path(@conn, :delete, track), method: :delete, data: [confirm: "Are you sure?"] %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= link "New Track", to: Routes.track_path(@conn, :new) %></span>

5
lib/dagon_web/templates/track/new.html.eex

@ -0,0 +1,5 @@
<h1>New Track</h1>
<%= render "form.html", Map.put(assigns, :action, Routes.track_path(@conn, :create)) %>
<span><%= link "Back", to: Routes.track_path(@conn, :index) %></span>

13
lib/dagon_web/templates/track/show.html.eex

@ -0,0 +1,13 @@
<h1>Show Track</h1>
<ul>
<li>
<strong>Name:</strong>
<%= @track.name %>
</li>
</ul>
<span><%= link "Edit", to: Routes.track_path(@conn, :edit, @track) %></span>
<span><%= link "Back", to: Routes.track_path(@conn, :index) %></span>

3
lib/dagon_web/views/album_view.ex

@ -0,0 +1,3 @@
defmodule DagonWeb.AlbumView do
use DagonWeb, :view
end

3
lib/dagon_web/views/artist_view.ex

@ -0,0 +1,3 @@
defmodule DagonWeb.ArtistView do
use DagonWeb, :view
end

3
lib/dagon_web/views/listen_view.ex

@ -0,0 +1,3 @@
defmodule DagonWeb.ListenView do
use DagonWeb, :view
end

3
lib/dagon_web/views/track_view.ex

@ -0,0 +1,3 @@
defmodule DagonWeb.TrackView do
use DagonWeb, :view
end

14
mix.exs

@ -33,16 +33,18 @@ defmodule Dagon.MixProject do
# Type `mix help deps` for examples and options.
defp deps do
[
{:ecto_sql, "~> 3.1"},
{:gettext, "~> 0.11"},
{:httpoison, "~> 1.6"},
{:jason, "~> 1.0"},
{:phoenix, "~> 1.4.10"},
{:phoenix_pubsub, "~> 1.1"},
{:phoenix_ecto, "~> 4.0"},
{:ecto_sql, "~> 3.1"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:gettext, "~> 0.11"},
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"}
{:phoenix_pubsub, "~> 1.1"},
{:plug_cowboy, "~> 2.0"},
{:postgrex, ">= 0.0.0"},
{:slugger, "~> 0.3.0"}
]
end

10
mix.lock

@ -1,4 +1,5 @@
%{
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
"cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm"},
@ -8,8 +9,14 @@
"ecto_sql": {:hex, :ecto_sql, "3.2.0", "751cea597e8deb616084894dd75cbabfdbe7255ff01e8c058ca13f0353a3921b", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"file_system": {:hex, :file_system, "0.2.7", "e6f7f155970975789f26e77b8b8d8ab084c59844d8ecfaf58cbda31c494d14aa", [:mix], [], "hexpm"},
"gettext": {:hex, :gettext, "0.17.0", "abe21542c831887a2b16f4c94556db9c421ab301aee417b7c4fbde7fbdbe01ec", [:mix], [], "hexpm"},
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"httpoison": {:hex, :httpoison, "1.6.1", "2ce5bf6e535cd0ab02e905ba8c276580bab80052c5c549f53ddea52d72e81f33", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
"phoenix": {:hex, :phoenix, "1.4.10", "619e4a545505f562cd294df52294372d012823f4fd9d34a6657a8b242898c255", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
@ -20,5 +27,8 @@
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
"postgrex": {:hex, :postgrex, "0.15.1", "23ce3417de70f4c0e9e7419ad85bdabcc6860a6925fe2c6f3b1b5b1e8e47bf2f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"slugger": {:hex, :slugger, "0.3.0", "efc667ab99eee19a48913ccf3d038b1fb9f165fa4fbf093be898b8099e61b6ed", [:mix], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"},
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
}

16
priv/repo/migrations/20191023181552_create_artists.exs

@ -0,0 +1,16 @@
defmodule Dagon.Repo.Migrations.CreateArtists do
use Ecto.Migration
def change do
create table(:artists) do
add :name, :string
add :slug, :string
add :mbid, :string
add :msid, :string
timestamps()
end
end
end

19
priv/repo/migrations/20191023205308_create_albums.exs

@ -0,0 +1,19 @@
defmodule Dagon.Repo.Migrations.CreateAlbums do
use Ecto.Migration
def change do
create table(:albums) do
add :name, :string
add :slug, :string
add :mbid, :string
add :msid, :string
add :artist_id, references(:artists, on_delete: :nothing)
timestamps()
end
create index(:albums, [:artist_id])
end
end

16
priv/repo/migrations/20191023205531_create_tracks.exs

@ -0,0 +1,16 @@
defmodule Dagon.Repo.Migrations.CreateTracks do
use Ecto.Migration
def change do
create table(:tracks) do
add :name, :string
add :album_id, references(:albums, on_delete: :nothing)
add :artist_id, references(:artists, on_delete: :nothing)
timestamps()
end
create index(:tracks, [:album_id])
create index(:tracks, [:artist_id])
end
end

18
priv/repo/migrations/20191023205705_create_listens.exs

@ -0,0 +1,18 @@
defmodule Dagon.Repo.Migrations.CreateListens do
use Ecto.Migration
def change do
create table(:listens) do
add :listened_at, :timestamptz
add :track_id, references(:tracks, on_delete: :nothing)
add :artist_id, references(:artists, on_delete: :nothing)
add :album_id, references(:albums, on_delete: :nothing)
timestamps()
end
create index(:listens, [:track_id])
create index(:listens, [:album_id])
create index(:listens, [:artist_id])
end
end

68
test/dagon/listens/albums_test.exs

@ -0,0 +1,68 @@
defmodule Dagon.Listens.AlbumsTest do
use Dagon.DataCase
alias Dagon.Listens.Albums
describe "albums" do
alias Dagon.Listens.Albums.Album
@valid_attrs %{mbid: "some mbid", name: "some name", slug: "some slug"}
@update_attrs %{mbid: "some updated mbid", name: "some updated name", slug: "some updated slug"}
@invalid_attrs %{mbid: nil, name: nil, slug: nil}
def album_fixture(attrs \\ %{}) do
{:ok, album} =
attrs
|> Enum.into(@valid_attrs)
|> Albums.create_album()
album
end
test "list_albums/0 returns all albums" do
album = album_fixture()
assert Albums.list_albums() == [album]
end
test "get_album!/1 returns the album with given id" do
album = album_fixture()
assert Albums.get_album!(album.id) == album
end
test "create_album/1 with valid data creates a album" do
assert {:ok, %Album{} = album} = Albums.create_album(@valid_attrs)
assert album.mbid == "some mbid"
assert album.name == "some name"
assert album.slug == "some slug"
end
test "create_album/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Albums.create_album(@invalid_attrs)
end
test "update_album/2 with valid data updates the album" do
album = album_fixture()
assert {:ok, %Album{} = album} = Albums.update_album(album, @update_attrs)
assert album.mbid == "some updated mbid"
assert album.name == "some updated name"
assert album.slug == "some updated slug"
end
test "update_album/2 with invalid data returns error changeset" do
album = album_fixture()
assert {:error, %Ecto.Changeset{}} = Albums.update_album(album, @invalid_attrs)
assert album == Albums.get_album!(album.id)
end
test "delete_album/1 deletes the album" do
album = album_fixture()
assert {:ok, %Album{}} = Albums.delete_album(album)
assert_raise Ecto.NoResultsError, fn -> Albums.get_album!(album.id) end
end
test "change_album/1 returns a album changeset" do
album = album_fixture()
assert %Ecto.Changeset{} = Albums.change_album(album)
end
end
end

66
test/dagon/listens/artists_test.exs

@ -0,0 +1,66 @@
defmodule Dagon.Listens.ArtistsTest do
use Dagon.DataCase
alias Dagon.Listens.Artists
describe "artists" do
alias Dagon.Listens.Artists.Artist
@valid_attrs %{name: "some name", slug: "some slug"}
@update_attrs %{name: "some updated name", slug: "some updated slug"}
@invalid_attrs %{name: nil, slug: nil}
def artist_fixture(attrs \\ %{}) do
{:ok, artist} =
attrs
|> Enum.into(@valid_attrs)
|> Artists.create_artist()
artist
end
test "list_artists/0 returns all artists" do
artist = artist_fixture()
assert Artists.list_artists() == [artist]
end
test "get_artist!/1 returns the artist with given id" do
artist = artist_fixture()
assert Artists.get_artist!(artist.id) == artist
end
test "create_artist/1 with valid data creates a artist" do
assert {:ok, %Artist{} = artist} = Artists.create_artist(@valid_attrs)
assert artist.name == "some name"
assert artist.slug == "some slug"
end
test "create_artist/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Artists.create_artist(@invalid_attrs)
end
test "update_artist/2 with valid data updates the artist" do
artist = artist_fixture()
assert {:ok, %Artist{} = artist} = Artists.update_artist(artist, @update_attrs)
assert artist.name == "some updated name"
assert artist.slug == "some updated slug"
end
test "update_artist/2 with invalid data returns error changeset" do
artist = artist_fixture()
assert {:error, %Ecto.Changeset{}} = Artists.update_artist(artist, @invalid_attrs)
assert artist == Artists.get_artist!(artist.id)
end
test "delete_artist/1 deletes the artist" do
artist = artist_fixture()
assert {:ok, %Artist{}} = Artists.delete_artist(artist)
assert_raise Ecto.NoResultsError, fn -> Artists.get_artist!(artist.id) end
end
test "change_artist/1 returns a artist changeset" do
artist = artist_fixture()
assert %Ecto.Changeset{} = Artists.change_artist(artist)
end
end
end

62
test/dagon/listens/listens_test.exs

@ -0,0 +1,62 @@
defmodule Dagon.Listens.Li