diff --git a/lib/live_beats/accounts/user.ex b/lib/live_beats/accounts/user.ex index e65ba48..f4bd555 100644 --- a/lib/live_beats/accounts/user.ex +++ b/lib/live_beats/accounts/user.ex @@ -4,7 +4,6 @@ defmodule LiveBeats.Accounts.User do alias LiveBeats.Accounts.{User, Identity} - @max_songs 30 schema "users" do field :email, :string @@ -62,12 +61,6 @@ defmodule LiveBeats.Accounts.User do |> validate_username() end - def songs_changeset(%User{} = user, params) do - user - |> cast(params, [:songs_number]) - |> validate_required([:songs_number]) - |> validate_number(:songs_number, less_than_or_equal_to: @max_songs) - end defp validate_email(changeset) do changeset diff --git a/lib/live_beats/media_library.ex b/lib/live_beats/media_library.ex index b4fd49b..652ed7c 100644 --- a/lib/live_beats/media_library.ex +++ b/lib/live_beats/media_library.ex @@ -11,6 +11,7 @@ defmodule LiveBeats.MediaLibrary do @pubsub LiveBeats.PubSub @auto_next_threshold_seconds 5 + @max_songs 30 defdelegate stopped?(song), to: Song defdelegate playing?(song), to: Song @@ -157,15 +158,31 @@ defmodule LiveBeats.MediaLibrary do Ecto.Multi.insert(acc, {:song, ref}, chset) end) - |> Ecto.Multi.update(:update_songs_number, fn acc -> - new_songs = acc |> Enum.filter(&match?({{:song, _ref}, _}, &1)) |> Enum.count() + |> Ecto.Multi.run(:valid_songs_number, fn _repo, changes -> user = Accounts.get_user!(user.id) + new_songs_count = changes |> Enum.filter(&match?({{:song, _ref}, _}, &1)) |> Enum.count() - user_params = %{ - songs_number: user.songs_number + new_songs - } - - Accounts.User.songs_changeset(user, user_params) + if user.songs_number + new_songs_count <= @max_songs do + {:ok, new_songs_count} + else + {:error, :songs_limit_exceeded} + end + end) + |> Ecto.Multi.update_all( + :update_songs_number, + fn %{valid_songs_number: new_songs_count} -> + from(u in Accounts.User, + where: u.id == ^user.id and u.songs_number == ^user.songs_number, + update: [inc: [songs_number: ^new_songs_count]] + ) + end, + [] + ) + |> Ecto.Multi.run(:is_songs_number_updated?, fn _repo, %{update_songs_number: result} -> + case result do + {1, _} -> {:ok, user} + _ -> {:error, :invalid} + end end) case LiveBeats.Repo.transaction(multi) do @@ -180,16 +197,14 @@ defmodule LiveBeats.MediaLibrary do |> Enum.into(%{})} {:error, failed_op, failed_val, _changes} -> - reason = - case {failed_op, format_errors(failed_val)} do - {:update_songs_number, %{songs_number: _errors}} -> - {:songs_number, :songs_limit_exceeded} - - _ -> - {:form, :invalid} + failed_op = + case failed_op do + {:song, number} -> "Song ##{String.to_integer(number) + 1}" + :is_songs_number_updated? -> :invalid + failed_op -> failed_op end - {:error, reason} + {:error, {failed_op, failed_val}} end end @@ -369,12 +384,4 @@ defmodule LiveBeats.MediaLibrary do end defp topic(user_id) when is_integer(user_id), do: "profile:#{user_id}" - - defp format_errors(changeset) do - Changeset.traverse_errors(changeset, fn {message, opts} -> - Regex.replace(~r"%{(\w+)}", message, fn _, key -> - opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string() - end) - end) - end end diff --git a/lib/live_beats_web/live/song_live/upload_form_component.ex b/lib/live_beats_web/live/song_live/upload_form_component.ex index f4e1793..1d3eec5 100644 --- a/lib/live_beats_web/live/song_live/upload_form_component.ex +++ b/lib/live_beats_web/live/song_live/upload_form_component.ex @@ -157,6 +157,10 @@ defmodule LiveBeatsWeb.SongLive.UploadFormComponent do defp file_error(%{kind: :invalid} = assigns), do: ~H|Something went wrong| + defp file_error(%{kind: %Ecto.Changeset{} = changeset} = assigns) do + ~H|<%= LiveBeatsWeb.ErrorHelpers.translate_changeset_errors(@kind) %>| + end + defp file_error(%{kind: {msg, opts}} = assigns) when is_binary(msg) and is_list(opts) do ~H|<%= LiveBeatsWeb.ErrorHelpers.translate_error(@kind) %>| end diff --git a/lib/live_beats_web/views/error_helpers.ex b/lib/live_beats_web/views/error_helpers.ex index 526a790..cc5cbab 100644 --- a/lib/live_beats_web/views/error_helpers.ex +++ b/lib/live_beats_web/views/error_helpers.ex @@ -63,4 +63,10 @@ defmodule LiveBeatsWeb.ErrorHelpers do Gettext.dgettext(LiveBeatsWeb.Gettext, "errors", msg, opts) end end + + def translate_changeset_errors(changeset) do + changeset.errors + |> Enum.map(fn {key, value} -> "#{key} #{translate_error(value)}" end) + |> Enum.join("\n") + end end