diff --git a/ideas.md b/ideas.md index 2cb74e3..ac5addc 100644 --- a/ideas.md +++ b/ideas.md @@ -1,3 +1,4 @@ - Write media datbase ID as metadata/to file/whatever so it gives us an option to retroactively match media to the DB down the line. Useful if someone moves the media without informing the UI - Use a UUID for the media database ID (or at least alongside it) - Look into this and its recommended plugins https://hexdocs.pm/ex_check/readme.html +- Add output template option for the source's friendly name diff --git a/lib/pinchflat/media_source/source.ex b/lib/pinchflat/media_source/source.ex index 3ca2039..374c614 100644 --- a/lib/pinchflat/media_source/source.ex +++ b/lib/pinchflat/media_source/source.ex @@ -5,6 +5,7 @@ defmodule Pinchflat.Sources.Source do use Ecto.Schema import Ecto.Changeset + import Pinchflat.Utils.ChangesetUtils alias Pinchflat.Media.MediaItem alias Pinchflat.Profiles.MediaProfile @@ -25,6 +26,7 @@ defmodule Pinchflat.Sources.Source do collection_name collection_id collection_type + friendly_name download_media original_url media_profile_id @@ -53,6 +55,7 @@ defmodule Pinchflat.Sources.Source do def changeset(source, attrs) do source |> cast(attrs, @allowed_fields) + |> dynamic_default(:friendly_name, fn cs -> get_field(cs, :collection_name) end) |> validate_required(@required_fields) |> unique_constraint([:collection_id, :media_profile_id]) end diff --git a/lib/pinchflat/sources.ex b/lib/pinchflat/sources.ex index d7f13ab..96f8f61 100644 --- a/lib/pinchflat/sources.ex +++ b/lib/pinchflat/sources.ex @@ -118,7 +118,7 @@ defmodule Pinchflat.Sources do defp add_source_details_by_collection_type(source, changeset, source_details) do %Ecto.Changeset{changes: changes} = changeset - collection_type = source.collection_type || changes[:collection_type] + collection_type = Ecto.Changeset.get_field(changeset, :collection_type) collection_changes = case collection_type do diff --git a/lib/pinchflat/utils/changeset_utils.ex b/lib/pinchflat/utils/changeset_utils.ex new file mode 100644 index 0000000..128a692 --- /dev/null +++ b/lib/pinchflat/utils/changeset_utils.ex @@ -0,0 +1,19 @@ +defmodule Pinchflat.Utils.ChangesetUtils do + @moduledoc """ + Utility methods for working with changesets + """ + + import Ecto.Changeset + + @doc """ + Sets the default value of a field if it is nil by applying the given function. + + Returns %Ecto.Changeset{}. + """ + def dynamic_default(changeset, key, value_fn) do + case get_field(changeset, key) do + nil -> put_change(changeset, key, value_fn.(changeset)) + _ -> changeset + end + end +end diff --git a/lib/pinchflat/utils/function_utils.ex b/lib/pinchflat/utils/function_utils.ex index c06866f..2bcfc60 100644 --- a/lib/pinchflat/utils/function_utils.ex +++ b/lib/pinchflat/utils/function_utils.ex @@ -1,6 +1,6 @@ defmodule Pinchflat.Utils.FunctionUtils do @moduledoc """ - Utility functions for working with functions + Utility methods for working with functions """ @doc """ diff --git a/lib/pinchflat/utils/string_utils.ex b/lib/pinchflat/utils/string_utils.ex index 5f23e6f..d96d6c1 100644 --- a/lib/pinchflat/utils/string_utils.ex +++ b/lib/pinchflat/utils/string_utils.ex @@ -1,6 +1,6 @@ defmodule Pinchflat.Utils.StringUtils do @moduledoc """ - Utility functions for working with strings + Utility methods for working with strings """ @doc """ diff --git a/priv/repo/migrations/20240220215056_add_not_null_to_friendly_name.exs b/priv/repo/migrations/20240220215056_add_not_null_to_friendly_name.exs new file mode 100644 index 0000000..86c58f2 --- /dev/null +++ b/priv/repo/migrations/20240220215056_add_not_null_to_friendly_name.exs @@ -0,0 +1,13 @@ +defmodule Pinchflat.Repo.Migrations.AddNotNullToFriendlyName do + use Ecto.Migration + + def change do + alter table(:sources) do + remove :friendly_name, :string + end + + alter table(:sources) do + add :friendly_name, :string, null: false + end + end +end diff --git a/test/pinchflat/sources_test.exs b/test/pinchflat/sources_test.exs index 495e288..edbf358 100644 --- a/test/pinchflat/sources_test.exs +++ b/test/pinchflat/sources_test.exs @@ -59,6 +59,35 @@ defmodule Pinchflat.SourcesTest do assert String.starts_with?(source.collection_id, "some_playlist_id_") end + test "you can specify a custom friendly_name" do + expect(YtDlpRunnerMock, :run, &runner_function_mock/3) + + valid_attrs = %{ + media_profile_id: media_profile_fixture().id, + original_url: "https://www.youtube.com/channel/abc123", + collection_type: "channel", + friendly_name: "some custom name" + } + + assert {:ok, %Source{} = source} = Sources.create_source(valid_attrs) + + assert source.friendly_name == "some custom name" + end + + test "friendly name is pulled from collection_name if not specified" do + expect(YtDlpRunnerMock, :run, &runner_function_mock/3) + + valid_attrs = %{ + media_profile_id: media_profile_fixture().id, + original_url: "https://www.youtube.com/channel/abc123", + collection_type: "channel" + } + + assert {:ok, %Source{} = source} = Sources.create_source(valid_attrs) + + assert source.friendly_name == "some channel name" + end + test "creation with invalid data returns error changeset" do assert {:error, %Ecto.Changeset{}} = Sources.create_source(@invalid_source_attrs) end diff --git a/test/pinchflat/utils/changeset_utils_test.exs b/test/pinchflat/utils/changeset_utils_test.exs new file mode 100644 index 0000000..83eadd7 --- /dev/null +++ b/test/pinchflat/utils/changeset_utils_test.exs @@ -0,0 +1,33 @@ +defmodule Pinchflat.Utils.ChangesetUtilsTest do + use ExUnit.Case, async: true + + defmodule MockSchema do + use Ecto.Schema + import Ecto.Changeset + import Pinchflat.Utils.ChangesetUtils + + schema "mock_schemas" do + field :title, :string + end + + def changeset(data, attrs) do + data + |> cast(attrs, [:title]) + |> dynamic_default(:title, fn _ -> "default" end) + end + end + + describe "dynamic_default/3" do + test "sets the default value if the field is nil" do + changeset = MockSchema.changeset(%MockSchema{}, %{}) + + assert Ecto.Changeset.get_change(changeset, :title) == "default" + end + + test "does not set the default value if the field is not nil" do + changeset = MockSchema.changeset(%MockSchema{}, %{title: "custom"}) + + assert Ecto.Changeset.get_change(changeset, :title) == "custom" + end + end +end