Ecto is the database wrapper and integrated query language for Elixir applications.
Schemas
Code Generation
$ mix phx.gen.html Accounts Profile profiles email:string age:integer
Schema Definition
defmodule MyApp.Accounts.User do
use Ecto.Schema
schema "users" do
field :name, :string
field :age, :integer
field :password, :string, virtual: true
timestamps()
end
end
Supported Field Types
| Field Type | Description |
|---|---|
:id |
Integer primary key |
:binary_id |
UUID primary key |
:string |
UTF-8 string |
:integer |
Standard integer |
:float |
Floating-point number |
:decimal |
Arbitrary precision decimal |
:boolean |
True / false value |
:map |
JSON or native map |
{:array, inner_type} |
Array of specified inner type |
Changesets and Validations
Defining a Changeset
def changeset(user, params \\ :empty) do
user
|> cast(params, ~w(name email), ~w(age))
|> 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, max: 160)
|> validate_number(:score, greater_than: 0)
|> validate_confirmation(:password, message: "does not match")
|> unique_constraint(:email)
|> foreign_key_constraint(:post_id)
|> assoc_constraint(:post)
end
Inspecting Changeset State
changeset.valid? # Boolean validation state
changeset.errors # List of validation errors
changeset.changes # Map of modified attributes
changeset.params[:title] # Raw input parameters
Mutating Changesets
changeset
|> put_change(:title, "New Title")
|> force_change(:title, "Forced Title")
|> update_change(:title, &(&1 <> "..."))
|> delete_change(:title)
|> add_error(:title, "cannot be blank")
Repository Operations (Repo)
Fetching Records
# Fetch by primary key
user = Repo.get(User, id)
user = Repo.get!(User, id)
# Fetch by attributes
user = Repo.get_by(User, email: "[email protected]")
Insert, Update, and Delete
# Persist changeset
case Repo.insert(changeset) do
{:ok, user} -> IO.puts("Created user: #{user.name}")
{:error, changeset} -> IO.inspect(changeset.errors)
end
Repo.update(changeset)
Repo.insert_or_update(changeset)
Repo.delete(user)
Ecto Queries
import Ecto.Query
query = from p in Post,
where: p.published == true,
where: [state: "published"],
order_by: [desc: p.inserted_at],
limit: 10,
preload: [:author, :comments],
select: p
posts = Repo.all(query)
```\n