See:
Create user changeset, put the auth assoc on that changeset:
iex(10)> user = User.changeset(%User{}, %{name: "xian"}) |> put_assoc(:auth, Auth.changeset(%Auth{}, %{email: "xian@"}))
#Ecto.Changeset<
action: nil,
changes: %{
auth: #Ecto.Changeset<
action: :insert,
changes: %{email: "xian@"},
errors: [],
data: #RedGreens.Auths.Auth<>,
valid?: true
>,
name: "xian"
},
errors: [],
data: #RedGreens.Users.User<>,
valid?: true
>
Insert user changeset, creates both user and nested auth:
iex(11)> user |> Repo.insert() [debug] QUERY OK db=0.3ms idle=1783.1ms
begin []
[debug] QUERY OK db=0.2ms
INSERT INTO "users" ("name","inserted_at","updated_at") VALUES ($1,$2,$3) RETURNING "id" ["xian", ~N[2021-02-24 06:02:12], ~N[2021-02-24 06:02:12]]
[debug] QUERY OK db=0.5ms
INSERT INTO "auths" ("email","user_id","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["xian@", 4, ~N[2021-02-24 06:02:12], ~N[2021-02-24 06:02:12]]
[debug] QUERY OK db=0.7ms
commit []
{:ok,
%RedGreens.Users.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
auth: %RedGreens.Auths.Auth{
__meta__: #Ecto.Schema.Metadata<:loaded, "auths">,
email: "xian@",
id: 4,
inserted_at: ~N[2021-02-24 06:02:12],
updated_at: ~N[2021-02-24 06:02:12],
user: #Ecto.Association.NotLoaded<association :user is not loaded>,
user_id: 4
},
id: 4,
inserted_at: ~N[2021-02-24 06:02:12],
name: "xian",
updated_at: ~N[2021-02-24 06:02:12]
}}
Create second user with same email:
iex(12)> user = User.changeset(%User{}, %{name: "another xian"}) |> put_assoc(:auth, Auth.changeset(%Auth{}, %{email: "xian@"}))
#Ecto.Changeset<
action: nil,
changes: %{
auth: #Ecto.Changeset<
action: :insert,
changes: %{email: "xian@"},
errors: [],
data: #RedGreens.Auths.Auth<>,
valid?: true
>,
name: "another xian"
},
errors: [],
data: #RedGreens.Users.User<>,
valid?: true
>
iex(13)> user |> Repo.insert() [debug] QUERY OK db=0.1ms idle=1590.7ms
begin []
[debug] QUERY OK db=0.3ms
INSERT INTO "users" ("name","inserted_at","updated_at") VALUES ($1,$2,$3) RETURNING "id" ["another xian", ~N[2021-02-24 06:02:24], ~N[2021-02-24 06:02:24]]
[debug] QUERY ERROR db=0.3ms
INSERT INTO "auths" ("email","user_id","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["xian@", 5, ~N[2021-02-24 06:02:24], ~N[2021-02-24 06:02:24]]
[debug] QUERY OK db=0.1ms
rollback []
{:error,
#Ecto.Changeset<
action: :insert,
changes: %{
auth: #Ecto.Changeset<
action: :insert,
changes: %{email: "xian@", user_id: nil},
errors: [
email: {"has already been taken",
[constraint: :unique, constraint_name: "auths_email_index"]}
],
data: #RedGreens.Auths.Auth<>,
valid?: false
>,
name: "another xian"
},
errors: [],
data: #RedGreens.Users.User<>,
valid?: false
>}
User was never inserted because assoc failed:
iex(15)> from(u in User, where: u.name == "another xian") |> Repo.all()
[debug] QUERY OK source="users" db=0.2ms queue=0.5ms idle=1046.1ms
SELECT u0."id", u0."name", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."name" = 'another xian') []
[]