roehst
July 21, 2023, 6:57pm
1
Hi, I have an Order
model that has_many
OrderItem
.
I want to be able to insert an order and its order items with a single changeset:
alias MyApp.Orders.Order
alias MyApp.Orders.OrderItem
order = %{
name: "Order 1",
order_items: [
%{
sku_id: 1,
quantity: 5
},
%{
sku_id: 2,
quantity: 10
}
]
}
%Order{}
|> Order.changeset(order)
|> MyApp.Repo.insert!()
But Ecto points that order_items must have an order_id.
How can I generate the IDs properly?
Perhaps I am doing it wrong and should use a Multi?
What you have is normally fine, but it requires that your Order.changeset
function has some stuff to make it work. Can you show what you have for that function?
Seconded! I’d check for a missing |> cast_assoc(:order_items)
.
Here’s an example from the Ecto Associations guide for reference:
Inserting parent and child records together
…
Using external data
# Params represent data from a form, API, CLI, etc
params = %{
"title" => "Shawshank Redemption",
"release_date" => "1994-10-14",
"characters" =>
[
%{"name" => "Andy Dufresne", "age" => "50"},
%{"name" => "Red", "age" => "60"}
]
}
%Movie{}
|> cast(params, [:title, :release_date])
|> cast_assoc(:characters)
|> Repo.insert()
1 Like
Check your OrderItem.changeset
function - it shouldn’t have validate_required
on order_id
, but this result suggests that it does.
roehst
July 24, 2023, 2:56pm
5
Thanks @benwilson512 and @al2o3cr
Removing validate_required from the changeset did it.
It also may be worth reviewing the assoc_constraint/3
and foreign_key_constraint/3
to see if that was what you actually want.
After some digging, I found this stackoverflow post which really helped explain the difference.
cast_assoc/3 is only used in the changesets of schemas that have has_one or has_many. It invokes the cast/3 validation in the changeset of the associated schema.
assoc_constraint/3 is used in the changesets of schemas that have belongs_to. It checks to make sure the parent schema is in the database so an orphaned record isn’t inserted.
foreign_key_constraint/3 is used similarly to assoc_constraint/…
1 Like