Hi all,
newbie speaking, so I’m probably having some fundamental misunderstanding here…
I’m looking at the Phoenix tutorial under
https://hexdocs.pm/phoenix/contexts.html#cross-context-dependencies
more specifically, the following code snippet:
def update_cart(%Cart{} = cart, attrs) do
changeset =
cart
|> Cart.changeset(attrs)
|> Ecto.Changeset.cast_assoc(:items, with: &CartItem.changeset/2)
and am baffled at where Ecto.Changeset.cast_assoc
is getting the attribute values for items from.
When I decorate the code like this
def update_cart(%Cart{} = cart, attrs) do
IO.inspect(attrs, label: "Attrs")
changeset =
cart
|> Cart.changeset(attrs)
|> IO.inspect(label: "Cart Changeset")
|> Ecto.Changeset.cast_assoc(:items, with: &CartItem.changeset/2)
|> IO.inspect(label: "Multi Changeset")
then I get the followng output:
Attrs: %{
"items" => %{
"0" => %{"_persistent_id" => "0", "id" => "1", "quantity" => "11"}
}
}
Cart Changeset: #Ecto.Changeset<action: nil, changes: %{}, errors: [],
data: #Demo.ShoppingCart.Cart<>, valid?: true>
Multi Changeset: #Ecto.Changeset<
action: nil,
changes: %{
items: [
#Ecto.Changeset<
action: :update,
changes: %{quantity: 11},
errors: [],
data: #Demo.ShoppingCart.CartItem<>,
valid?: true
>
]
},
errors: [],
data: #Demo.ShoppingCart.Cart<>,
valid?: true
>
To me, the sequence looks like this:
- Items are in the
attrs
parameter, as expected. - Again, as expected, they are dropped when constructing the changeset for
Cart
. - Then, they magically reappear in the next step of the pipe, in the “multi changeset”.
Where were they hidden in the meantime?
Is there any hidden payload in Ecto.Changeset
that stores the original attributes?