Slide 1

Slide 1 text

Ecto Embedded Schemas Rémi Prévost Montreal Elixir Meetup 2018/05/09

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

params = %{ "author_name" => "Rémi Prévost", "published" => true, "title" => %{ "en" => "My new article in english",
 "fr" => "Mon nouvel article en français" } } %App.Blog.Article{} |> App.Blog.Article.changeset(params) |> App.Repo.insert!()

Slide 4

Slide 4 text

Schema-less data Map → JSON → Map

Slide 5

Slide 5 text

defmodule App.Blog.Article do use Ecto.Schema import Ecto.Changeset schema "articles" do field(:author_name, :string) field(:published, :boolean) field(:title, :map) end def changeset(%__MODULE__{} = record, params) do record |> cast(~w(author_name published title)a, params) |> validate_required(~w(author_name title)a) |> validate_change(:title, &validate_nested_french_value/2) end
 defp validate_nested_french_value(field, %{"fr" => fr}) when fr != "", do: [] defp validate_nested_french_value(field, _) do [{field, "must specify french value"}] end end

Slide 6

Slide 6 text

App.Blog.Article |> App.Repo.get(1) %App.Blog.Article{ id: 1, author_name: "Rémi Prévost", published: true, title: %{ en: "My new article in english",
 fr: "Mon nouvel article in english" } }

Slide 7

Slide 7 text

defmodule App.Payments.Transaction do use Ecto.Schema import Ecto.Changeset schema "payment_transations" do field(:gateway_response, :map) belongs_to(:order_id, App.Order) end def changeset(%__MODULE__{} = record, params) do record |> cast(~w(order_id gateway_response)a, params) |> validate_required(~w(order_id)a) end end

Slide 8

Slide 8 text

Embedded schema Schema → JSON → Schema

Slide 9

Slide 9 text

defmodule App.Blog.Article do use Ecto.Schema import Ecto.Changeset schema "articles" do field(:author_name, :string)
 field(:published, :boolean) embeds_one(:title, App.Translations.Translated) end def changeset(%__MODULE__{} = record, params) do record |> cast(~w(author_name published)a, params) |> validate_required(~w(author_name)a) |> cast_embed(:title, required: true) end end

Slide 10

Slide 10 text

defmodule App.Translations.Translated do use Ecto.Schema import Ecto.Changeset embedded_schema do field(:en, :string) field(:fr, :string) end def changeset(%__MODULE__{} = record, params) do record |> cast(~w(en fr)a, params) |> validate_required(~w(fr)a) end end

Slide 11

Slide 11 text

App.Blog.Article |> App.Repo.get(1) %App.Blog.Article{ id: 1, author_name: "Rémi Prévost",
 published: true, title: %App.Translations.Translated{ id: "602975a2-bfbd-4c48-9d60-0b955ccc4bc7", en: "My new article in english", fr: "Mon nouvel article en français" } }

Slide 12

Slide 12 text

That’s it! Ecto.Schema and Ecto.Changeset are awesome.