Skip to content

Instantly share code, notes, and snippets.

@joeljuca
Created October 22, 2024 21:08
Show Gist options
  • Save joeljuca/2039e22f11161318c6172841acb9b07d to your computer and use it in GitHub Desktop.
Save joeljuca/2039e22f11161318c6172841acb9b07d to your computer and use it in GitHub Desktop.
defmodule MyApp.Accounts do
# (...)
@spec sign_up(params :: %{String.t() => String.t()}) ::
{:ok, User.t()} | {:error, Ecto.Changeset.t()}
def sign_up(%{} = params) do
# Here, a list of params and their types
params_schema = %{
name: :string,
# (...)
}
# Here I set up a schemaless validation
# (A bit verbose, like you said - but it's worth the LOCs)
changeset =
{%{}, params_schema}
|> cast(params, Map.keys(params_schema))
|> validate_required([:name, :email, :etc])
# (...) Some more validation, if needed
# I don't do lots of validations here because they'll probably be duplicates
# of ones defined by some `changeset/2` function (in this example,
# `User.changeset/2`).
# Here's the thing: the call to `apply_action/2` is made inside the `with`,
# turning its returned errors part of the Core function return types,
# alongside ones from `create_user/1`, making it easier to react to errors
# in param validation from whichever Interface you'll be using this
# Core function.
with {:ok, params} <- apply_action(changeset, :sign_up),
{:ok, user} <- create_user(params) do
{:ok, user}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment