2

Phoenix: Ecto models cheatsheet

 2 years ago
source link: https://devhints.io/[email protected]
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

This is for Phoenix 1.2 and below. Phoenix 1.3 has a new API..

Generating

$ mix phoenix.gen.html Profile profiles email:string age:integer
$ mix phoenix.gen.html User users email:string hashed_password:string

Schema

defmodule User do
  use Ecto.Schema

  schema "users" do
    field :name
    field :age, :integer
    # :id :binary :integer :float :boolean :string :binary
    # {:array, inner_type} :decimal :map

    field :password, virtual: true
  end
end

Changesets

def changeset(user, params \\ :empty) do
  %User{}
  |> Ecto.Changeset.change   # basic casting to changeset

  user
  |> cast(params, ~w(name email), ~w(age)) # params to Changeset

  |> validate_format(:email, ~r/@/)

  |> validate_inclusion(:age, 18..100)
  |> validate_exclusion(:role, ~w(admin superadmin))
  |> validate_subset(:pets, ~w(cat dog parrot whale))

  |> validate_length(:body, min: 1)
  |> validate_length(:body, min: 1, max: 160)
  |> validate_length(:partners, is: 2)

  |> validate_number(:pi, greater_than: 3)
  |> validate_number(:pi, less_than: 4)
  |> validate_number(:pi, equal_to: 42)

  |> validate_change(:title, fn _, _ -> [])
  |> validate_confirmation(:password, message: "does not match")

  |> unique_constraint(:email)
  |> foreign_key_constraint(:post_id)
  |> assoc_constraint(:post)      # ensure post_id exists
  |> no_assoc_constraint(:post)   # negative (useful for deletions)
end
changeset.valid?
changeset.errors     #=> [title: "empty"]

changeset.changes    #=> %{}
changeset.params[:title]

changeset.required   #=> [:title]
changeset.optional   #=> [:body]

Updating

changeset #(or model)
|> change(title: "New title")
|> change(%{ title: "New title" })
|> put_change(:title, "New title")
|> force_change(:title, "New title")
|> update_change(:title, &(&1 <> "..."))

|> delete_change(:title)
|> merge(other_changeset)

|> add_error(:title, "empty")

Getting

get_change(changeset, :title)    #=> "hi" (if changed)
get_field(changeset, :title)     #=> "hi" (even if unchanged)

fetch_change(changeset, :title)  #=> {:ok, "hi"} | :error
fetch_field(changeset, :title)   #=> {:changes | :model, "value"} | :error

Get one

Repo.get(User, id)
Repo.get_by(User, email: "[email protected]")  #=> %User{} | nil

# also get! get_by!

Create/update

changeset |> Repo.update
changeset |> Repo.insert
changeset |> Repo.insert_or_update
User
|> Ecto.Changeset.change(%{name: "hi"})
|> Repo.insert

Queries

from p in Post,
  where: p.title == "Hello",
  where: [state: "Sweden"],

  limit: 1,
  offset: 10,

  order_by: c.name,
  order_by: [c.name, c.title],
  order_by: [asc: c.name, desc: c.title],

  preload: [:comments],
  preload: [comments: {c, likes: l}],

  join: c in assoc(c, :comments),
  join: p in Post, on: c.post_id == p.id,
  group_by: p,

  select: p,
  select: {p.title, p.description},
  select: [p.title, p.description],

Get many

Repo.all(User)

Update many

Repo.update_all(Post, set: [title: "Title"])
Repo.update_all(Post, inc: [views: 1])

Chaining _all with queries

from(p in Post, where: p.id < 10)
|> Repo.update_all(...)

from(p in Post, where: p.id < 10)
|> Repo.all()

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK