From 8f130a7598d2030b30617c5929504d074fad12b0 Mon Sep 17 00:00:00 2001 From: shibao Date: Mon, 31 Jan 2022 23:45:00 -0500 Subject: [PATCH] add types to ecto changeset specs --- CONTRIBUTING.md | 2 +- lib/cannery/accounts.ex | 20 +++++++++++--------- lib/cannery/accounts/user.ex | 24 +++++++++++++----------- lib/cannery/ammo.ex | 22 ++++++++++++++-------- lib/cannery/ammo/ammo_group.ex | 2 +- lib/cannery/ammo/ammo_type.ex | 2 +- lib/cannery/containers.ex | 18 ++++++++++-------- lib/cannery/containers/container.ex | 2 +- lib/cannery/containers/container_tag.ex | 3 ++- lib/cannery/invites.ex | 22 ++++++++++++---------- lib/cannery/invites/invite.ex | 2 +- lib/cannery/tags.ex | 11 ++++++----- lib/cannery/tags/tag.ex | 2 +- 13 files changed, 74 insertions(+), 58 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4cd291ca..f3756ece 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ contributing to Cannery (hopefully) as great of an experience as you found it! inline `do:` blocks for short functions and make your aliases as short as possible without introducing ambiguity. - I.e. since there's only one `Changeset` in the app, please alias - `Changeset.t()` instead of using `Ecto.Changeset.t()` + `Changeset.t(Type.t())` instead of using `Ecto.Changeset.t(Long.Type.t())` - Use pipelines when possible. If a function only calls a single method, a pipeline isn't strictly necessary but still encouraged for future modification. diff --git a/lib/cannery/accounts.ex b/lib/cannery/accounts.ex index 130415b2..a1b1f064 100644 --- a/lib/cannery/accounts.ex +++ b/lib/cannery/accounts.ex @@ -89,7 +89,7 @@ defmodule Cannery.Accounts do {:error, %Changeset{}} """ - @spec register_user(map()) :: {:ok, User.t()} | {:error, Changeset.t()} + @spec register_user(map()) :: {:ok, User.t()} | {:error, Changeset.t(User.new_user())} def register_user(attrs) do # if no registered users, make first user an admin attrs = @@ -109,8 +109,10 @@ defmodule Cannery.Accounts do %Changeset{data: %User{}} """ - @spec change_user_registration(User.t() | User.new_user()) :: Changeset.t() - @spec change_user_registration(User.t() | User.new_user(), map()) :: Changeset.t() + @spec change_user_registration(User.t() | User.new_user()) :: + Changeset.t(User.t() | User.new_user()) + @spec change_user_registration(User.t() | User.new_user(), map()) :: + Changeset.t(User.t() | User.new_user()) def change_user_registration(user, attrs \\ %{}), do: User.registration_changeset(user, attrs, hash_password: false) @@ -125,7 +127,7 @@ defmodule Cannery.Accounts do %Changeset{data: %User{}} """ - @spec change_user_email(User.t(), map()) :: Changeset.t() + @spec change_user_email(User.t(), map()) :: Changeset.t(User.t()) def change_user_email(user, attrs \\ %{}), do: User.email_changeset(user, attrs) @doc """ @@ -137,7 +139,7 @@ defmodule Cannery.Accounts do %Changeset{data: %User{}} """ - @spec change_user_role(User.t(), atom()) :: Changeset.t() + @spec change_user_role(User.t(), atom()) :: Changeset.t(User.t()) def change_user_role(user, role), do: User.role_changeset(user, role) @doc """ @@ -154,7 +156,7 @@ defmodule Cannery.Accounts do """ @spec apply_user_email(User.t(), String.t(), map()) :: - {:ok, User.t()} | {:error, Changeset.t()} + {:ok, User.t()} | {:error, Changeset.t(User.t())} def apply_user_email(user, password, attrs) do user |> User.email_changeset(attrs) @@ -218,7 +220,7 @@ defmodule Cannery.Accounts do %Changeset{data: %User{}} """ - @spec change_user_password(User.t(), map()) :: Changeset.t() + @spec change_user_password(User.t(), map()) :: Changeset.t(User.t()) def change_user_password(user, attrs \\ %{}), do: User.password_changeset(user, attrs, hash_password: false) @@ -235,7 +237,7 @@ defmodule Cannery.Accounts do """ @spec update_user_password(User.t(), String.t(), map()) :: - {:ok, User.t()} | {:error, Changeset.t()} + {:ok, User.t()} | {:error, Changeset.t(User.t())} def update_user_password(user, password, attrs) do changeset = user @@ -399,7 +401,7 @@ defmodule Cannery.Accounts do {:error, %Changeset{}} """ - @spec reset_user_password(User.t(), map()) :: {:ok, User.t()} | {:error, Changeset.t()} + @spec reset_user_password(User.t(), map()) :: {:ok, User.t()} | {:error, Changeset.t(User.t())} def reset_user_password(user, attrs) do Multi.new() |> Multi.update(:user, User.password_changeset(user, attrs)) diff --git a/lib/cannery/accounts/user.ex b/lib/cannery/accounts/user.ex index 95508490..2545c9b6 100644 --- a/lib/cannery/accounts/user.ex +++ b/lib/cannery/accounts/user.ex @@ -54,9 +54,9 @@ defmodule Cannery.Accounts.User do validations on a LiveView form), this option can be set to `false`. Defaults to `true`. """ - @spec registration_changeset(t() | new_user(), attrs :: map()) :: Changeset.t() + @spec registration_changeset(t() | new_user(), attrs :: map()) :: Changeset.t(t() | new_user()) @spec registration_changeset(t() | new_user(), attrs :: map(), opts :: keyword()) :: - Changeset.t() + Changeset.t(t() | new_user()) def registration_changeset(user, attrs, opts \\ []) do user |> cast(attrs, [:email, :password, :role]) @@ -68,12 +68,12 @@ defmodule Cannery.Accounts.User do A user changeset for role. """ - @spec role_changeset(t(), role :: atom()) :: Changeset.t() + @spec role_changeset(t(), role :: atom()) :: Changeset.t(t()) def role_changeset(user, role) do user |> cast(%{"role" => role}, [:role]) end - @spec validate_email(Changeset.t()) :: Changeset.t() + @spec validate_email(Changeset.t(t() | new_user())) :: Changeset.t(t() | new_user()) defp validate_email(changeset) do changeset |> validate_required([:email]) @@ -83,7 +83,8 @@ defmodule Cannery.Accounts.User do |> unique_constraint(:email) end - @spec validate_password(Changeset.t(), opts :: keyword()) :: Changeset.t() + @spec validate_password(Changeset.t(t() | new_user()), opts :: keyword()) :: + Changeset.t(t() | new_user()) defp validate_password(changeset, opts) do changeset |> validate_required([:password]) @@ -94,7 +95,8 @@ defmodule Cannery.Accounts.User do |> maybe_hash_password(opts) end - @spec maybe_hash_password(Changeset.t(), opts :: keyword()) :: Changeset.t() + @spec maybe_hash_password(Changeset.t(t() | new_user()), opts :: keyword()) :: + Changeset.t(t() | new_user()) defp maybe_hash_password(changeset, opts) do hash_password? = Keyword.get(opts, :hash_password, true) password = get_change(changeset, :password) @@ -113,7 +115,7 @@ defmodule Cannery.Accounts.User do It requires the email to change otherwise an error is added. """ - @spec email_changeset(t(), attrs :: map()) :: Changeset.t() + @spec email_changeset(t(), attrs :: map()) :: Changeset.t(t()) def email_changeset(user, attrs) do user |> cast(attrs, [:email]) @@ -136,8 +138,8 @@ defmodule Cannery.Accounts.User do validations on a LiveView form), this option can be set to `false`. Defaults to `true`. """ - @spec password_changeset(t(), attrs :: map()) :: Changeset.t() - @spec password_changeset(t(), attrs :: map(), opts :: keyword()) :: Changeset.t() + @spec password_changeset(t(), attrs :: map()) :: Changeset.t(t()) + @spec password_changeset(t(), attrs :: map(), opts :: keyword()) :: Changeset.t(t()) def password_changeset(user, attrs, opts \\ []) do user |> cast(attrs, [:password]) @@ -148,7 +150,7 @@ defmodule Cannery.Accounts.User do @doc """ Confirms the account by setting `confirmed_at`. """ - @spec confirm_changeset(t() | Changeset.t()) :: Changeset.t() + @spec confirm_changeset(t() | Changeset.t(t())) :: Changeset.t(t()) def confirm_changeset(user_or_changeset) do now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) user_or_changeset |> change(confirmed_at: now) @@ -174,7 +176,7 @@ defmodule Cannery.Accounts.User do @doc """ Validates the current password otherwise adds an error to the changeset. """ - @spec validate_current_password(Changeset.t(), String.t()) :: Changeset.t() + @spec validate_current_password(Changeset.t(t()), String.t()) :: Changeset.t(t()) def validate_current_password(changeset, password) do if valid_password?(changeset.data, password), do: changeset, diff --git a/lib/cannery/ammo.ex b/lib/cannery/ammo.ex index 40b9391d..e485176e 100644 --- a/lib/cannery/ammo.ex +++ b/lib/cannery/ammo.ex @@ -49,7 +49,8 @@ defmodule Cannery.Ammo do {:error, %Ecto.Changeset{}} """ - @spec create_ammo_type(attrs :: map()) :: {:ok, AmmoType.t()} | {:error, Changeset.t()} + @spec create_ammo_type(attrs :: map()) :: + {:ok, AmmoType.t()} | {:error, Changeset.t(AmmoType.new_ammo_type())} def create_ammo_type(attrs \\ %{}), do: %AmmoType{} |> AmmoType.changeset(attrs) |> Repo.insert() @@ -66,7 +67,7 @@ defmodule Cannery.Ammo do """ @spec update_ammo_type(AmmoType.t(), attrs :: map()) :: - {:ok, AmmoType.t()} | {:error, Changeset.t()} + {:ok, AmmoType.t()} | {:error, Changeset.t(AmmoType.t())} def update_ammo_type(%AmmoType{} = ammo_type, attrs), do: ammo_type |> AmmoType.changeset(attrs) |> Repo.update() @@ -82,7 +83,8 @@ defmodule Cannery.Ammo do {:error, %Ecto.Changeset{}} """ - @spec delete_ammo_type(AmmoType.t()) :: {:ok, AmmoType.t()} | {:error, Changeset.t()} + @spec delete_ammo_type(AmmoType.t()) :: + {:ok, AmmoType.t()} | {:error, Changeset.t(AmmoType.t())} def delete_ammo_type(%AmmoType{} = ammo_type), do: ammo_type |> Repo.delete() @doc """ @@ -106,8 +108,10 @@ defmodule Cannery.Ammo do %Ecto.Changeset{data: %AmmoType{}} """ - @spec change_ammo_type(AmmoType.t() | AmmoType.new_ammo_type()) :: Changeset.t() - @spec change_ammo_type(AmmoType.t() | AmmoType.new_ammo_type(), attrs :: map()) :: Changeset.t() + @spec change_ammo_type(AmmoType.t() | AmmoType.new_ammo_type()) :: + Changeset.t(AmmoType.t() | AmmoType.new_ammo_type()) + @spec change_ammo_type(AmmoType.t() | AmmoType.new_ammo_type(), attrs :: map()) :: + Changeset.t(AmmoType.t() | AmmoType.new_ammo_type()) def change_ammo_type(%AmmoType{} = ammo_type, attrs \\ %{}), do: AmmoType.changeset(ammo_type, attrs) @@ -159,7 +163,8 @@ defmodule Cannery.Ammo do {:error, %Ecto.Changeset{}} """ - @spec create_ammo_group(attrs :: map()) :: {:ok, AmmoGroup.t()} | {:error, Changeset.t()} + @spec create_ammo_group(attrs :: map()) :: + {:ok, AmmoGroup.t()} | {:error, Changeset.t(AmmoGroup.new_ammo_group())} def create_ammo_group(attrs \\ %{}), do: %AmmoGroup{} |> AmmoGroup.changeset(attrs) |> Repo.insert() @@ -176,7 +181,7 @@ defmodule Cannery.Ammo do """ @spec update_ammo_group(AmmoGroup.t(), attrs :: map()) :: - {:ok, AmmoGroup.t()} | {:error, Changeset.t()} + {:ok, AmmoGroup.t()} | {:error, Changeset.t(AmmoGroup.t())} def update_ammo_group(%AmmoGroup{} = ammo_group, attrs), do: ammo_group |> AmmoGroup.changeset(attrs) |> Repo.update() @@ -192,7 +197,8 @@ defmodule Cannery.Ammo do {:error, %Ecto.Changeset{}} """ - @spec delete_ammo_group(AmmoGroup.t()) :: {:ok, AmmoGroup.t()} | {:error, Changeset.t()} + @spec delete_ammo_group(AmmoGroup.t()) :: + {:ok, AmmoGroup.t()} | {:error, Changeset.t(AmmoGroup.t())} def delete_ammo_group(%AmmoGroup{} = ammo_group), do: ammo_group |> Repo.delete() @doc """ diff --git a/lib/cannery/ammo/ammo_group.ex b/lib/cannery/ammo/ammo_group.ex index 261ddd26..463b70cf 100644 --- a/lib/cannery/ammo/ammo_group.ex +++ b/lib/cannery/ammo/ammo_group.ex @@ -47,7 +47,7 @@ defmodule Cannery.Ammo.AmmoGroup do @type id :: UUID.t() @doc false - @spec changeset(t() | new_ammo_group(), attrs :: map()) :: Changeset.t() + @spec changeset(t() | new_ammo_group(), attrs :: map()) :: Changeset.t(t() | new_ammo_group()) def changeset(ammo_group, attrs) do ammo_group |> cast(attrs, [:count, :price_paid, :notes, :tag_id, :ammo_type_id, :container_id, :user_id]) diff --git a/lib/cannery/ammo/ammo_type.ex b/lib/cannery/ammo/ammo_type.ex index e29d21f1..4cc007ad 100644 --- a/lib/cannery/ammo/ammo_type.ex +++ b/lib/cannery/ammo/ammo_type.ex @@ -38,7 +38,7 @@ defmodule Cannery.Ammo.AmmoType do @type id :: UUID.t() @doc false - @spec changeset(t() | new_ammo_type(), attrs :: map()) :: Changeset.t() + @spec changeset(t() | new_ammo_type(), attrs :: map()) :: Changeset.t(t() | new_ammo_type()) def changeset(ammo_type, attrs) do ammo_type |> cast(attrs, [:name, :desc, :case_material, :bullet_type, :grain, :manufacturer]) diff --git a/lib/cannery/containers.ex b/lib/cannery/containers.ex index 096737cc..39100acb 100644 --- a/lib/cannery/containers.ex +++ b/lib/cannery/containers.ex @@ -50,7 +50,8 @@ defmodule Cannery.Containers do {:error, %Ecto.Changeset{}} """ - @spec create_container(attrs :: map()) :: {:ok, Container.t()} | {:error, Changeset.t()} + @spec create_container(attrs :: map()) :: + {:ok, Container.t()} | {:error, Changeset.t(Container.new_container())} def create_container(attrs) do %Container{} |> Container.changeset(attrs) |> Repo.insert() end @@ -67,8 +68,8 @@ defmodule Cannery.Containers do {:error, %Ecto.Changeset{}} """ - @spec update_container(Container.t() | Ecto.Changeset.t(), attrs :: map()) :: - {:ok, Container.t()} | {:error, Ecto.Changeset.t()} + @spec update_container(Container.t(), attrs :: map()) :: + {:ok, Container.t()} | {:error, Changeset.t(Container.t())} def update_container(container, attrs) do container |> Container.changeset(attrs) |> Repo.update() end @@ -85,8 +86,8 @@ defmodule Cannery.Containers do {:error, %Ecto.Changeset{}} """ - @spec delete_container(Container.t() | Ecto.Changeset.t()) :: - {:ok, Container.t()} | {:error, Ecto.Changeset.t()} + @spec delete_container(Container.t()) :: + {:ok, Container.t()} | {:error, Changeset.t(Container.t())} def delete_container(container), do: container |> Repo.delete() @doc """ @@ -98,7 +99,7 @@ defmodule Cannery.Containers do %Container{} """ - @spec delete_container!(Container.t() | Ecto.Changeset.t()) :: Container.t() + @spec delete_container!(Container.t()) :: Container.t() def delete_container!(container), do: container |> Repo.delete!() @doc """ @@ -113,9 +114,10 @@ defmodule Cannery.Containers do %Ecto.Changeset{data: %Container{}} """ - @spec change_container(Container.t() | Container.new_container()) :: Changeset.t() + @spec change_container(Container.t() | Container.new_container()) :: + Changeset.t(Container.t() | Container.new_container()) @spec change_container(Container.t() | Container.new_container(), attrs :: map()) :: - Changeset.t() + Changeset.t(Container.t() | Container.new_container()) def change_container(container, attrs \\ %{}), do: container |> Container.changeset(attrs) @doc """ diff --git a/lib/cannery/containers/container.ex b/lib/cannery/containers/container.ex index d7718436..15339dc1 100644 --- a/lib/cannery/containers/container.ex +++ b/lib/cannery/containers/container.ex @@ -36,7 +36,7 @@ defmodule Cannery.Containers.Container do @type id :: UUID.t() @doc false - @spec changeset(t() | new_container(), attrs :: map()) :: Changeset.t() + @spec changeset(t() | new_container(), attrs :: map()) :: Changeset.t(t() | new_container()) def changeset(container, attrs) do container |> cast(attrs, [:name, :desc, :type, :location, :user_id]) diff --git a/lib/cannery/containers/container_tag.ex b/lib/cannery/containers/container_tag.ex index ac4ad835..ee0f8ee5 100644 --- a/lib/cannery/containers/container_tag.ex +++ b/lib/cannery/containers/container_tag.ex @@ -31,7 +31,8 @@ defmodule Cannery.Containers.ContainerTag do @type id :: UUID.t() @doc false - @spec changeset(t() | new_container_tag(), attrs :: map()) :: Changeset.t() + @spec changeset(t() | new_container_tag(), attrs :: map()) :: + Changeset.t(t() | new_container_tag()) def changeset(container_tag, attrs) do container_tag |> cast(attrs, [:tag_id, :container_id]) diff --git a/lib/cannery/invites.ex b/lib/cannery/invites.ex index bf8ab43e..45033c75 100644 --- a/lib/cannery/invites.ex +++ b/lib/cannery/invites.ex @@ -93,11 +93,11 @@ defmodule Cannery.Invites do {:ok, %Invite{}} iex> create_invite(%User{id: "1"}, %{field: bad_value}) - {:error, %Ecto.Changeset{}} + {:error, %Changeset{}} """ @spec create_invite(User.t() | User.id(), attrs :: map()) :: - {:ok, Invite.t()} | {:error, Changeset.t()} + {:ok, Invite.t()} | {:error, Changeset.t(Invite.new_invite())} def create_invite(%{id: user_id}, attrs), do: create_invite(user_id, attrs) def create_invite(user_id, attrs) when not (user_id |> is_nil()) do @@ -120,11 +120,11 @@ defmodule Cannery.Invites do {:ok, %Invite{}} iex> update_invite(invite, %{field: bad_value}) - {:error, %Ecto.Changeset{}} + {:error, %Changeset{}} """ @spec update_invite(Invite.t(), attrs :: map()) :: - {:ok, Invite.t()} | {:error, Ecto.Changeset.t()} + {:ok, Invite.t()} | {:error, Changeset.t(Invite.t())} def update_invite(invite, attrs), do: invite |> Invite.changeset(attrs) |> Repo.update() @doc """ @@ -136,10 +136,10 @@ defmodule Cannery.Invites do {:ok, %Invite{}} iex> delete_invite(invite) - {:error, %Ecto.Changeset{}} + {:error, %Changeset{}} """ - @spec delete_invite(Invite.t()) :: {:ok, Invite.t()} | {:error, Ecto.Changeset.t()} + @spec delete_invite(Invite.t()) :: {:ok, Invite.t()} | {:error, Changeset.t(Invite.t())} def delete_invite(invite), do: invite |> Repo.delete() @doc """ @@ -155,15 +155,17 @@ defmodule Cannery.Invites do def delete_invite!(invite), do: invite |> Repo.delete!() @doc """ - Returns an `%Ecto.Changeset{}` for tracking invite changes. + Returns an `%Changeset{}` for tracking invite changes. ## Examples iex> change_invite(invite) - %Ecto.Changeset{data: %Invite{}} + %Changeset{data: %Invite{}} """ - @spec change_invite(Invite.t() | Invite.new_invite()) :: Ecto.Changeset.t() - @spec change_invite(Invite.t() | Invite.new_invite(), attrs :: map()) :: Ecto.Changeset.t() + @spec change_invite(Invite.t() | Invite.new_invite()) :: + Changeset.t(Invite.t() | Invite.new_invite()) + @spec change_invite(Invite.t() | Invite.new_invite(), attrs :: map()) :: + Changeset.t(Invite.t() | Invite.new_invite()) def change_invite(invite, attrs \\ %{}), do: invite |> Invite.changeset(attrs) end diff --git a/lib/cannery/invites/invite.ex b/lib/cannery/invites/invite.ex index 36031c17..e3e06e91 100644 --- a/lib/cannery/invites/invite.ex +++ b/lib/cannery/invites/invite.ex @@ -38,7 +38,7 @@ defmodule Cannery.Invites.Invite do @type id :: UUID.t() @doc false - @spec changeset(t() | new_invite(), attrs :: map()) :: Changeset.t() + @spec changeset(t() | new_invite(), attrs :: map()) :: Changeset.t(t() | new_invite()) def changeset(invite, attrs) do invite |> cast(attrs, [:name, :token, :uses_left, :disabled_at, :user_id]) diff --git a/lib/cannery/tags.ex b/lib/cannery/tags.ex index 5ff7ad18..8ee6cee1 100644 --- a/lib/cannery/tags.ex +++ b/lib/cannery/tags.ex @@ -49,7 +49,7 @@ defmodule Cannery.Tags do {:error, %Changeset{}} """ - @spec create_tag(attrs :: map()) :: {:ok, Tag.t()} | {:error, Changeset.t()} + @spec create_tag(attrs :: map()) :: {:ok, Tag.t()} | {:error, Changeset.t(Tag.new_tag())} def create_tag(attrs), do: %Tag{} |> Tag.changeset(attrs) |> Repo.insert() @doc """ @@ -64,7 +64,7 @@ defmodule Cannery.Tags do {:error, %Changeset{}} """ - @spec update_tag(Tag.t(), attrs :: map()) :: {:ok, Tag.t()} | {:error, Changeset.t()} + @spec update_tag(Tag.t(), attrs :: map()) :: {:ok, Tag.t()} | {:error, Changeset.t(Tag.t())} def update_tag(tag, attrs), do: tag |> Tag.changeset(attrs) |> Repo.update() @doc """ @@ -79,7 +79,7 @@ defmodule Cannery.Tags do {:error, %Changeset{}} """ - @spec delete_tag(Tag.t()) :: {:ok, Tag.t()} | {:error, Changeset.t()} + @spec delete_tag(Tag.t()) :: {:ok, Tag.t()} | {:error, Changeset.t(Tag.t())} def delete_tag(tag), do: tag |> Repo.delete() @doc """ @@ -103,8 +103,9 @@ defmodule Cannery.Tags do %Changeset{data: %Tag{}} """ - @spec change_tag(Tag.t() | Tag.new_tag()) :: Changeset.t() - @spec change_tag(Tag.t() | Tag.new_tag(), attrs :: map()) :: Changeset.t() + @spec change_tag(Tag.t() | Tag.new_tag()) :: Changeset.t(Tag.t() | Tag.new_tag()) + @spec change_tag(Tag.t() | Tag.new_tag(), attrs :: map()) :: + Changeset.t(Tag.t() | Tag.new_tag()) def change_tag(tag, attrs \\ %{}), do: Tag.changeset(tag, attrs) @doc """ diff --git a/lib/cannery/tags/tag.ex b/lib/cannery/tags/tag.ex index 5abc8e5b..2f74436f 100644 --- a/lib/cannery/tags/tag.ex +++ b/lib/cannery/tags/tag.ex @@ -35,7 +35,7 @@ defmodule Cannery.Tags.Tag do @type id() :: UUID.t() @doc false - @spec changeset(t() | new_tag(), attrs :: map()) :: Changeset.t() + @spec changeset(t() | new_tag(), attrs :: map()) :: Changeset.t(t() | new_tag()) def changeset(tag, attrs) do tag |> cast(attrs, [:name, :bg_color, :text_color, :user_id])