From 38bbb94f7c1e64cf29156201a6cfcee15c668733 Mon Sep 17 00:00:00 2001 From: "Rico Sta. Cruz" Date: Tue, 29 Aug 2017 16:57:58 +0800 Subject: [PATCH] Update ecto --- phoenix-ecto.md | 174 +------------------------------------------ phoenix-ecto@1.2.md | 177 ++++++++++++++++++++++++++++++++++++++++++++ phoenix-ecto@1.3.md | 13 +++- 3 files changed, 188 insertions(+), 176 deletions(-) create mode 100644 phoenix-ecto@1.2.md diff --git a/phoenix-ecto.md b/phoenix-ecto.md index 09b04c7e1..4a0d58666 100644 --- a/phoenix-ecto.md +++ b/phoenix-ecto.md @@ -1,177 +1,5 @@ --- title: "Phoenix: Ecto models" category: Elixir +redirect_to: /phoenix-ecto@1.3 --- - -This is for Phoenix 1.2 and below. [Phoenix 1.3 has a new API.](phoenix-ecto@1.3.html). - -## Generating - -``` -$ mix phoenix.gen.html Profile profiles email:string age:integer -$ mix phoenix.gen.html User users email:string hashed_password:string -``` - -## Schema - -```elixir -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 - -```elixir -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 -``` - -```elixir -changeset.valid? -changeset.errors #=> [title: "empty"] - -changeset.changes #=> %{} -changeset.params[:title] - -changeset.required #=> [:title] -changeset.optional #=> [:body] -``` - -### Updating - -```elixir -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 - -```elixir -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 -``` - -## Ecto - -### Get one - -```elixir -Repo.get(User, id) -Repo.get_by(User, email: "john@hello.com") #=> %User{} | nil - -# also get! get_by! -``` - -### Create/update - -```elixir -changeset |> Repo.update -changeset |> Repo.insert -changeset |> Repo.insert_or_update -``` - -``` -User -|> Ecto.Changeset.change(%{name: "hi"}) -|> Repo.insert -``` - -## Many - -### Queries - -```elixir -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 - -```elixir -Repo.all(User) -``` - -### Update many - -```elixir -Repo.update_all(Post, set: [title: "Title"]) -Repo.update_all(Post, inc: [views: 1]) -``` - -### Chaining `_all` with queries - -```elixir -from(p in Post, where: p.id < 10) -|> Repo.update_all(...) - -from(p in Post, where: p.id < 10) -|> Repo.all() -``` diff --git a/phoenix-ecto@1.2.md b/phoenix-ecto@1.2.md new file mode 100644 index 000000000..09b04c7e1 --- /dev/null +++ b/phoenix-ecto@1.2.md @@ -0,0 +1,177 @@ +--- +title: "Phoenix: Ecto models" +category: Elixir +--- + +This is for Phoenix 1.2 and below. [Phoenix 1.3 has a new API.](phoenix-ecto@1.3.html). + +## Generating + +``` +$ mix phoenix.gen.html Profile profiles email:string age:integer +$ mix phoenix.gen.html User users email:string hashed_password:string +``` + +## Schema + +```elixir +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 + +```elixir +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 +``` + +```elixir +changeset.valid? +changeset.errors #=> [title: "empty"] + +changeset.changes #=> %{} +changeset.params[:title] + +changeset.required #=> [:title] +changeset.optional #=> [:body] +``` + +### Updating + +```elixir +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 + +```elixir +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 +``` + +## Ecto + +### Get one + +```elixir +Repo.get(User, id) +Repo.get_by(User, email: "john@hello.com") #=> %User{} | nil + +# also get! get_by! +``` + +### Create/update + +```elixir +changeset |> Repo.update +changeset |> Repo.insert +changeset |> Repo.insert_or_update +``` + +``` +User +|> Ecto.Changeset.change(%{name: "hi"}) +|> Repo.insert +``` + +## Many + +### Queries + +```elixir +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 + +```elixir +Repo.all(User) +``` + +### Update many + +```elixir +Repo.update_all(Post, set: [title: "Title"]) +Repo.update_all(Post, inc: [views: 1]) +``` + +### Chaining `_all` with queries + +```elixir +from(p in Post, where: p.id < 10) +|> Repo.update_all(...) + +from(p in Post, where: p.id < 10) +|> Repo.all() +``` diff --git a/phoenix-ecto@1.3.md b/phoenix-ecto@1.3.md index 38cfb0087..ff8f0057d 100644 --- a/phoenix-ecto@1.3.md +++ b/phoenix-ecto@1.3.md @@ -1,16 +1,19 @@ --- title: "Phoenix: Ecto models" category: Elixir +layout: 2017/sheet +tags: [WIP] +updated: 201708.29 --- -## Generating +### Generating ``` $ mix phx.gen.html Accounts Profile profiles email:string age:integer $ mix phx.gen.html Accounts User users email:string hashed_password:string ``` -## Schema +### Schema ```elixir defmodule Myapp.Accounts.User do @@ -31,6 +34,8 @@ end ## Changesets +### Changesets + ```elixir def changeset(user, params \\ :empty) do %User{} @@ -63,6 +68,8 @@ def changeset(user, params \\ :empty) do end ``` +### Changeset fields + ```elixir changeset.valid? changeset.errors #=> [title: "empty"] @@ -100,7 +107,7 @@ fetch_change(changeset, :title) #=> {:ok, "hi"} | :error fetch_field(changeset, :title) #=> {:changes | :model, "value"} | :error ``` -## Ecto +## Repo ### Get one