2 title: "Phoenix: Ecto models"
7 archived: This is for Phoenix 1.2 and below. [Phoenix 1.3 has a new API.](./phoenix-ecto@1.3).
12 This is for Phoenix 1.2 and below. [Phoenix 1.3 has a new API.](./phoenix-ecto@1.3).
17 $ mix phoenix.gen.html Profile profiles email:string age:integer
18 $ mix phoenix.gen.html User users email:string hashed_password:string
30 # :id :binary :integer :float :boolean :string :binary
31 # {:array, inner_type} :decimal :map
33 field :password, virtual: true
41 def changeset(user, params \\ :empty) do
43 |> Ecto.Changeset.change # basic casting to changeset
46 |> cast(params, ~w(name email), ~w(age)) # params to Changeset
48 |> validate_format(:email, ~r/@/)
50 |> validate_inclusion(:age, 18..100)
51 |> validate_exclusion(:role, ~w(admin superadmin))
52 |> validate_subset(:pets, ~w(cat dog parrot whale))
54 |> validate_length(:body, min: 1)
55 |> validate_length(:body, min: 1, max: 160)
56 |> validate_length(:partners, is: 2)
58 |> validate_number(:pi, greater_than: 3)
59 |> validate_number(:pi, less_than: 4)
60 |> validate_number(:pi, equal_to: 42)
62 |> validate_change(:title, fn _, _ -> [])
63 |> validate_confirmation(:password, message: "does not match")
65 |> unique_constraint(:email)
66 |> foreign_key_constraint(:post_id)
67 |> assoc_constraint(:post) # ensure post_id exists
68 |> no_assoc_constraint(:post) # negative (useful for deletions)
74 changeset.errors #=> [title: "empty"]
76 changeset.changes #=> %{}
77 changeset.params[:title]
79 changeset.required #=> [:title]
80 changeset.optional #=> [:body]
87 |> change(title: "New title")
88 |> change(%{ title: "New title" })
89 |> put_change(:title, "New title")
90 |> force_change(:title, "New title")
91 |> update_change(:title, &(&1 <> "..."))
93 |> delete_change(:title)
94 |> merge(other_changeset)
96 |> add_error(:title, "empty")
102 get_change(changeset, :title) #=> "hi" (if changed)
103 get_field(changeset, :title) #=> "hi" (even if unchanged)
105 fetch_change(changeset, :title) #=> {:ok, "hi"} | :error
106 fetch_field(changeset, :title) #=> {:changes | :model, "value"} | :error
115 Repo.get_by(User, email: "john@hello.com") #=> %User{} | nil
123 changeset |> Repo.update
124 changeset |> Repo.insert
125 changeset |> Repo.insert_or_update
130 |> Ecto.Changeset.change(%{name: "hi"})
140 where: p.title == "Hello",
141 where: [state: "Sweden"],
147 order_by: [c.name, c.title],
148 order_by: [asc: c.name, desc: c.title],
150 preload: [:comments],
151 preload: [comments: {c, likes: l}],
153 join: c in assoc(c, :comments),
154 join: p in Post, on: c.post_id == p.id,
158 select: {p.title, p.description},
159 select: [p.title, p.description],
171 Repo.update_all(Post, set: [title: "Title"])
172 Repo.update_all(Post, inc: [views: 1])
175 ### Chaining `_all` with queries
178 from(p in Post, where: p.id < 10)
179 |> Repo.update_all(...)
181 from(p in Post, where: p.id < 10)