Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ecto Embedded Schemas

Ecto Embedded Schemas

We’ll take a look at how Ecto’s embedded schemas can help us persist and retrieve structured and meaningful data using database JSON columns.

This is a lightning talk I gave at the May 2018 Montreal Elixir Meetup hosted by Mirego.

Avatar for Rémi Prévost

Rémi Prévost

May 09, 2018
Tweet

More Decks by Rémi Prévost

Other Decks in Technology

Transcript

  1. 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!()
  2. 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
  3. 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" } }
  4. 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
  5. 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
  6. 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
  7. 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" } }