Craft graphql api with Absinthe book- Subscriptions chapter 6 place orders

Hi everyone,

So following the absinthe book I arrived at the subscription chapter with the ordering system powered by embedded schemas.

My problem is that cast/4 is deprecated but I couldn’t find any example of cast_embed/3

My Order schema looks like this:

defmodule PlateSlate.Ordering.Order do
  use Ecto.Schema
  import Ecto.Changeset
  alias PlateSlate.Ordering.Order

  schema "orders" do
    field :customer_number, :integer, read_after_writes: true
    field :ordered_at, :utc_datetime, read_after_writes: true
    field :state, :string, read_after_writes: true
    embeds_many :items, PlateSlate.Ordering.Item
    timestamps()
  end

  @doc false
  def changeset(%Order{} = order, attrs) do
    order
    |> cast(attrs, [:customer_number, :items, :ordered_at, :state])
    |> cast_embed(:items)
  end
end

My Item schema looks like this:

defmodule PlateSlate.Ordering.Item do
  use Ecto.Schema
  import Ecto.Changeset

  embedded_schema do
    field :price, :decimal
    field :name, :string
    field :quantity, :integer
  end

  def changeset(item, attrs) do
    item
    |> cast(attrs, [:price, :name, :quantity])
    |> validate_required([:price, :name, :quantity])
  end
end

Error trace:

mix test test/plate_slate/ordering_test.exs                                                                   1 ✘  at 17:23:35 


  1) test orders create_order/1 with valid data creates a order (PlateSlate.OrderingTest)
     test/plate_slate/ordering_test.exs:13
     ** (RuntimeError) casting embeds with cast/4 for :items field is not supported, use cast_embed/3 instead
     code: assert {:ok, %Order{} = order} = Ordering.create_order(attrs)
     stacktrace:
       (ecto) lib/ecto/changeset.ex:545: Ecto.Changeset.type!/2
       (ecto) lib/ecto/changeset.ex:519: Ecto.Changeset.process_param/7
       (elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
       (ecto) lib/ecto/changeset.ex:504: Ecto.Changeset.cast/6
       (plate_slate) lib/plate_slate/ordering/order.ex:17: PlateSlate.Ordering.Order.changeset/2
       (plate_slate) lib/plate_slate/ordering.ex:56: PlateSlate.Ordering.create_order/1
       test/plate_slate/ordering_test.exs:24: (test)



Finished in 0.1 seconds
1 test, 1 failure

Also, I don’t have any embeds in my test file, so the error is definitely coming from my schemas, just wondering what is the correct way to define cast_embed/3

Because I think that how it is now it should be correct.
Thanks in advance

1 Like

Hello!
Just remove :items from the list of attributes on cast call.

1 Like

Thanks @fuelen,

That is the solution.

Can I also add that the error I got is misleading and doesn’t explain what is really happening?

Thanks again for the help

I think the error makes sense if you know what it’s saying.

Items is an embed, and the error is telling you you tried to cast an embedded field in cast/4, which is not allowed.

Even though you did a cast_embed after, it hits this error first.

1 Like

Thanks @Adzz for the follow up on this.

But I think that a more clearer way to define this error should be like this:

Embeded field detected and is not permitted in cast

I think that this should make more sense to everybody and also an exmaple in the docs.