Ecto: How to update and insert association in one update using put_assoc
Asked Answered
M

2

9

I'm trying to write a single changeset that will update a model and insert an association. I cannot find examples on how to use put_assoc/4

  order = order
    |> Proj.Order.changeset(%{state: "error", error_count: order.error_count + 1})
    |> Ecto.Changeset.put_assoc(
      :order_errors,
      [Proj.OrderError.changeset(%Proj.OrderError{}, %{reason: "not_found"})])
    |> Proj.Repo.update!

This prints out the following error:

** (Ecto.InvalidChangesetError) could not perform update because changeset is invalid.

* Changeset changes

%{order_errors: [%Ecto.Changeset{action: :insert, changes: %{id: nil, inserted_at: nil, order_id: nil, reason: "not_found", updated_at: nil}, constraints: [], errors: [order_id: "can't be blank"], filters: %{}, model: %Proj.OrderError{__meta__: #Ecto.Schema.Metadata<:built>, id: nil, inserted_at: nil, order: #Ecto.Association.NotLoaded<association :order is not loaded>, order_id: nil, reason: nil, updated_at: nil}, optional: [], opts: [], params: %{"reason" => "not_found"}, prepare: [], repo: nil, required: [:order_id, :reason], types: %{id: :id, inserted_at: Ecto.DateTime, order_id: :id, reason: :string, updated_at: Ecto.DateTime}, valid?: false, validations: []}], state: "error"}

* Changeset params

%{"error_count" => 1, "state" => "error"}

* Changeset errors

[]

Any examples I can look at for put_assoc/4? How can I find why the changeset is invalid?

The goal of doing things this way is that I hope the new order would have order_errors preloaded.

Maricruzmaridel answered 19/2, 2016 at 21:8 Comment(0)
M
5

I found how to make it work in the Ecto tests. Short story, simply remove the changeset creation and use directly a new model.

  order = order
    |> Proj.Order.changeset(%{state: "error", error_count: order.error_count + 1})
    |> Ecto.Changeset.put_assoc(
      :order_errors,
      [%Proj.OrderError{reason: "not_found"}])
    |> Proj.Repo.update!

I'd still like to know how to understand the error message from the original post

Maricruzmaridel answered 19/2, 2016 at 21:15 Comment(0)
A
0

As put_assoc/4 describes the valid value:

The given value may either be the association struct, a changeset for the given association or a map or keyword list of changes to be applied to the current association. On all cases, it is expected the keys to be atoms. If a map or keyword list are given and there is no association, one will be created.

If you use the changeset, you should use the existed %Proj.OrderError{}, the put_assoc/4 will auto do the update for this changeset.

But to other situation, especially the record need insert, use struct ,keyword lists or map is better idea.

Aphyllous answered 2/5, 2018 at 8:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.