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

Ecto: a database wrapper and language integrated query for Elixir

Ecto: a database wrapper and language integrated query for Elixir

Arjan van der Gaag

October 28, 2015
Tweet

More Decks by Arjan van der Gaag

Other Decks in Programming

Transcript

  1. ecto
    a database wrapper and language
    integrated query for Elixir

    View Slide

  2. defmodule Weather do
    use Ecto.Model
    schema "weather" do
    field :city # Defaults to type :string
    field :temp_lo, :integer
    field :temp_hi, :integer
    field :prcp, :float, default: 0.0
    end
    end
    query = from w in Weather,
    where: w.prcp > 0 or is_nil(w.prcp),
    select: w
    Repo.all(query)

    View Slide

  3. simplicity over
    convenience

    View Slide

  4. “If you want Ecto to get something, you
    have to explicitly ask for it. This
    feature will probably seem a little
    tedious to you…”

    View Slide

  5. “…but it is the only way to guarantee
    your application has predictable
    performance when the amount of
    data grows.”

    View Slide

  6. defmodule Weather do
    use Ecto.Model
    schema "weather" do
    field :city # Defaults to type :string
    field :temp_lo, :integer
    field :temp_hi, :integer
    field :prcp, :float, default: 0.0
    end
    end
    query = from w in Weather,
    where: w.prcp > 0 or is_nil(w.prcp),
    select: w
    Repo.all(query)

    View Slide

  7. defmodule Weather do
    use Ecto.Model
    schema "weather" do
    field :city # Defaults to type :string
    field :temp_lo, :integer
    field :temp_hi, :integer
    field :prcp, :float, default: 0.0
    end
    end
    query = from w in Weather,
    where: w.prcp > 0 or is_nil(w.prcp),
    select: w
    Repo.all(query)

    View Slide

  8. defmodule Weather do
    use Ecto.Model
    schema "weather" do
    field :city # Defaults to type :string
    field :temp_lo, :integer
    field :temp_hi, :integer
    field :prcp, :float, default: 0.0
    end
    end
    query = from w in Weather,
    where: w.prcp > 0 or is_nil(w.prcp),
    select: w
    Repo.all(query)

    View Slide

  9. defmodule Weather do
    use Ecto.Model
    schema "weather" do
    field :city # Defaults to type :string
    field :temp_lo, :integer
    field :temp_hi, :integer
    field :prcp, :float, default: 0.0
    end
    end
    query = from w in Weather,
    where: w.prcp > 0 or is_nil(w.prcp),
    select: w
    Repo.all(query)

    View Slide

  10. defmodule Weather do
    use Ecto.Model
    schema "weather" do
    field :city # Defaults to type :string
    field :temp_lo, :integer
    field :temp_hi, :integer
    field :prcp, :float, default: 0.0
    end
    end
    query = from w in Weather,
    where: w.prcp > 0 or is_nil(w.prcp),
    select: w
    Repo.all(query)

    View Slide

  11. ‣ data mapper
    ‣ query language
    ‣ associations
    ‣ filtering
    ‣ validations
    ‣ lifecycle callbacks
    ‣ changesets
    ‣ migrations
    ‣ custom types
    ‣ embedded structs

    View Slide

  12. compose queries

    View Slide

  13. # Create a query
    query = from w in Weather, where: w.prcp > 0
    # Extend the query
    query = from w in query, select: w.city

    View Slide

  14. repository

    View Slide

  15. Repo.get_by(Post, title: "My post")
    Repo.transaction(fn ->
    Repo.update!(%{alice | balance: alice.balance - 10})
    Repo.update!(%{bob | balance: bob.balance + 10})
    end)
    post = Repo.get!(Post, 42)
    post = %{post | title: "New title"}
    case Repo.update post do
    {:ok, model} -> # Updated with success
    {:error, changeset} -> # Something went wrong
    end

    View Slide

  16. Repo.get_by(Post, title: "My post")
    Repo.transaction(fn ->
    Repo.update!(%{alice | balance: alice.balance - 10})
    Repo.update!(%{bob | balance: bob.balance + 10})
    end)
    post = Repo.get!(Post, 42)
    post = %{post | title: "New title"}
    case Repo.update post do
    {:ok, model} -> # Updated with success
    {:error, changeset} -> # Something went wrong
    end

    View Slide

  17. Repo.get_by(Post, title: "My post")
    Repo.transaction(fn ->
    Repo.update!(%{alice | balance: alice.balance - 10})
    Repo.update!(%{bob | balance: bob.balance + 10})
    end)
    post = Repo.get!(Post, 42)
    post = %{post | title: "New title"}
    case Repo.update post do
    {:ok, model} -> # Updated with success
    {:error, changeset} -> # Something went wrong
    end

    View Slide

  18. changesets

    View Slide

  19. defmodule User do
    use Ecto.Model
    import Ecto.Changeset
    schema "users" do
    field :name
    field :email
    field :age, :integer
    end
    def changeset(user, params \\ :empty) do
    user
    |> cast(params, ~w(name email), ~w(age))
    |> validate_format(:email, ~r/@/)
    |> unique_constraint(:email)
    |> validate_inclusion(:age, 18..100)
    end
    end

    View Slide

  20. defmodule User do
    use Ecto.Model
    import Ecto.Changeset
    schema "users" do
    field :name
    field :email
    field :age, :integer
    end
    def changeset(user, params \\ :empty) do
    user
    |> cast(params, ~w(name email), ~w(age))
    |> validate_format(:email, ~r/@/)
    |> unique_constraint(:email)
    |> validate_inclusion(:age, 18..100)
    end
    end

    View Slide

  21. defmodule User do
    use Ecto.Model
    import Ecto.Changeset
    schema "users" do
    field :name
    field :email
    field :age, :integer
    end
    def changeset(user, params \\ :empty) do
    user
    |> cast(params, ~w(name email), ~w(age))
    |> validate_format(:email, ~r/@/)
    |> unique_constraint(:email)
    |> validate_inclusion(:age, 18..100)
    end
    end

    View Slide

  22. defmodule User do
    use Ecto.Model
    import Ecto.Changeset
    schema "users" do
    field :name
    field :email
    field :age, :integer
    end
    def changeset(user, params \\ :empty) do
    user
    |> cast(params, ~w(name email), ~w(age))
    |> validate_format(:email, ~r/@/)
    |> unique_constraint(:email)
    |> validate_inclusion(:age, 18..100)
    end
    end

    View Slide

  23. defmodule User do
    use Ecto.Model
    import Ecto.Changeset
    schema "users" do
    field :name
    field :email
    field :age, :integer
    end
    def changeset(user, params \\ :empty) do
    user
    |> cast(params, ~w(name email), ~w(age))
    |> validate_format(:email, ~r/@/)
    |> unique_constraint(:email)
    |> validate_inclusion(:age, 18..100)
    end
    end

    View Slide

  24. defmodule User do
    use Ecto.Model
    import Ecto.Changeset
    schema "users" do
    field :name
    field :email
    field :age, :integer
    end
    def changeset(user, params \\ :empty) do
    user
    |> cast(params, ~w(name email), ~w(age))
    |> validate_format(:email, ~r/@/)
    |> unique_constraint(:email)
    |> validate_inclusion(:age, 18..100)
    end
    end

    View Slide

  25. def registration_changeset(model, params) do
    model
    |> changeset(params)
    |> cast(params, ~w(password), [])
    |> validate_length(:password, min: 6, max: 100)
    |> put_pass_hash()
    end

    View Slide

  26. associations

    View Slide

  27. query = from p in Post, preload: [:comments]
    query = from p in Post,
    join: c in assoc(p, :comments),
    where: c.published_at > p.updated_at,
    preload: [comments: c]
    query |> Repo.all

    View Slide

  28. familiar
    different
    pragmatic
    fun

    View Slide