View Source EctoShorts.CommonChanges (ecto_shorts v2.4.0)
CommonChanges
is a collection of functions to help with managing
and creating our &changeset/2
function in our schemas.
Preloading associations on change
Often times we want to be able to change an association with
(put/cast)_assoc
, but we have an awkwardness of having to use
a preload in a spot to do this. We can aleviate that by doing the following:
defmodule MyApp.Accounts.User do
def changeset(changeset, params) do
changeset
|> cast([:name, :email])
|> validate_required([:name, :email])
|> EctoShorts.CommonChanges.preload_change_assoc(:address)
end
end
Doing this allows us to then pass address in via a map, or even using the struct from the database directly to add as a relation
Validating relation is passed in somehow
We can validate for a relation being passed in via id or by using our preload_change_assoc by doing the following:
defmodule MyApp.Accounts.User do
def changeset(changeset, params) do
changeset
|> cast([:name, :email, :address_id])
|> validate_required([:name, :email])
|> EctoShorts.CommonChanges.preload_change_assoc(:address,
required_when_missing: :address_id
)
end
end
Conditional functions
We can also run functions when something happens by defining conditional functions like so:
defmodule MyApp.Accounts.User do
alias EctoShorts.CommonChanges
def changeset(changeset, params) do
changeset
|> cast([:name, :email, :address_id])
|> validate_required([:name, :email])
|> CommonChanges.put_when(
&CommonChanges.changeset_field_nil?(&1, :email),
&put_change(&1, :email, "some_default@gmail.com")
)
end
end
Summary
Functions
Checks if field on changeset is empty list in data or changes
Checks if field on changeset is nil in data or changes
This function is the primary use function Preloads changeset assoc if change is made and then and put_or_cast's it
Preloads a changesets association
Determines put or cast on association with some special magic
Run's changeset function if when function returns true
Functions
@spec changeset_field_empty?(Ecto.Changeset.t(), atom()) :: boolean()
Checks if field on changeset is empty list in data or changes
@spec changeset_field_nil?(Ecto.Changeset.t(), atom()) :: boolean()
Checks if field on changeset is nil in data or changes
@spec preload_change_assoc(Ecto.Changeset.t(), atom()) :: Ecto.Changeset.t()
@spec preload_change_assoc(Ecto.Changeset.t(), atom(), keyword()) :: Ecto.Changeset.t()
This function is the primary use function Preloads changeset assoc if change is made and then and put_or_cast's it
Example
iex> CommonChanges.preload_change_assoc(changeset, :my_relation) iex> CommonChanges.preload_change_assoc(changeset, :my_relation, repo: MyApp.OtherRepo) iex> CommonChanges.preload_change_assoc(changeset, :my_relation, required: true) iex> CommonChanges.preload_change_assoc(changeset, :my_relation, required_when_missing: :my_relation_id)
@spec preload_changeset_assoc(Ecto.Changeset.t(), atom(), keyword()) :: Ecto.Changeset.t()
Preloads a changesets association
@spec put_or_cast_assoc(Ecto.Changeset.t(), atom(), Keyword.t()) :: Ecto.Changeset.t()
Determines put or cast on association with some special magic
If you pass a many to many relation only a list of id's it will count that as a member_update
and remove or add members to the relations list
E.G. User many_to_many Fruit
This would update the user to have only fruits with id 1 and 3
CommonChanges.put_or_cast_assoc(change(user, fruits: [%{id: 1}, %{id: 3}]), :fruits)
@spec put_when( Ecto.Changeset.t(), (Ecto.Changeset.t() -> boolean()), (Ecto.Changeset.t() -> Ecto.Changeset.t()) ) :: Ecto.Changeset.t()
Run's changeset function if when function returns true