Ecto Changeset in Contexts

A while back I read on the elixir forum that Saša Jurić prefers to have the Ecto changeset functions, as private functions, in the contexts rather than the schemas themselves.

After experimenting with it in a personal project, it started to make sense. While the documentation of both Ecto and Phoenix suggests to place the changeset functions in the schemas, it actually makes more sense to me to place them in the contexts.

In another blog post Tracy show how using multiple changesets work better in Elixir (still in the schema though).

Both those posts made me want to try this out and I'm pleased with the end result:

defmodule Orders do
import Ecto.Changeset

@spec create_order(map, Shop.t()) :: {:ok, Order.t()} | {:error, Ecto.Changeset.t(Order.t())}
def create_order(params, shop) do
|> Ecto.build_assoc(:orders)
|> order_changeset(params)
|> put_order_number_change() # only needed when creating an order
|> (...) # more create related changeset operations
|> Repo.insert()

# General changeset that can be used on create and update
defp order_changeset(order, params) do
|> cast(params, [:email, ...])
|> validate_required([:email, ...])

elixir ecto phoenix