Skip to content

Instantly share code, notes, and snippets.

@kwando
Created September 14, 2022 09:00
Show Gist options
  • Save kwando/cc69846dd5423b8ddd2a62acd11920af to your computer and use it in GitHub Desktop.
Save kwando/cc69846dd5423b8ddd2a62acd11920af to your computer and use it in GitHub Desktop.
Ecto param schemas [livebook]

Ecto Schema

Mix.install([:ecto])

Section

defmodule ParamSchema do
  defmodule ValidationError do
    defstruct [:errors]
  end

  defmacro __using__(_opts) do
    quote do
      use Ecto.Schema
      import Ecto.Changeset
      @primary_key false

      def create(params) do
        ParamSchema.create(__MODULE__, params)
      end

      def validate(changeset) do
        changeset
      end

      defoverridable validate: 1
    end
  end

  def create(module, params) do
    changeset =
      struct(module)
      |> Ecto.Changeset.cast(Map.new(params), module.__schema__(:fields))
      |> module.validate()

    if changeset.valid? do
      {:ok, Ecto.Changeset.apply_changes(changeset)}
    else
      {:error, %ValidationError{errors: changeset.errors}}
    end
  end
end

Defining schemas will be like this then

defmodule CreateUserParams do
  use ParamSchema

  embedded_schema do
    field(:name, :string)
    field(:email, :string)
  end

  def validate(changeset) do
    changeset
    |> validate_required([:name, :email])
  end
end

With valid params:

CreateUserParams.create(email: "test@example.com", name: "Alice")

With invalid params.

CreateUserParams.create(email: "test@example.com")

We could process the errors more if we wanna hide teh ecto internals

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment