Embedded schema for form validation and casting
As useful as Ecto schemas are for databases, they are just as compelling for handling Form parameters. The key is using embedded_schema
.
Define an embedded_schema that represents the request parameters with the types:
defmodule P do use Ecto.Schema embedded_schema do field :an_int, :integer field :a_date, :date end end
Then use cast to get the parameters safely and with typing into a changeset:
iex(3)> p = cast( %P{}, %{ "an_int" => "4", "a_date" => "2019-04-04" }, [ :an_int, :a_date ] ) #Ecto.Changeset< action: nil, changes: %{a_date: ~D[2019-04-04], an_int: 4}, errors: [], data: #P<>, valid?: true >
If the changeset is valid, then you can use apply_changes
to get the struct you wanted:
iex(5)> apply_changes(p) %P{a_date: ~D[2019-04-04], an_int: 4, id: nil}
You can also use all the typical validators the Changeset offers.
If some of the data is bad/mistyped, the changeset will mark it as valid? false:
iex(6)> cast( %P{}, %{ "an_int" => "fred", "a_date" => "2019-04-04" }, [ :an_int, :a_date ] ) #Ecto.Changeset< action: nil, changes: %{a_date: ~D[2019-04-04]}, errors: [an_int: {"is invalid", [type: :integer, validation: :cast]}], data: #P<>, valid?: false >