I"m trying to update a record with an embeds_many field, but get the error listed in (3) below. In the schema for the parent object, I use on_replace: :delete
, since without it I also get an error on update. The ecto docs suggest using this, but something must still not be right. I can create data in the embeds_many
field. But once created, I cannot change it. (See Note (4))
(1) Schema of parent object
schema "documents" do
field :content, :string
field :rendered_content, :string
field :title, :string
field :author_id, :integer
field :attributes, :map
field :tags, {:array, :string}
field :identifier, :string
embeds_many :children, Child, on_replace: :delete
timestamps()
end
(2) Child schema
defmodule Child do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :level, :integer
field :title, :string
field :doc_id, :integer
field :doc_identifier, :string
field :comment, :string
end
def changeset(%Child{} = child, attrs) do
child
|> cast(attrs, [:level, :title, :doc_id, :doc_identifier, :comment])
end
end
(3) Error message
[debug] QUERY OK db=8.2ms
UPDATE "documents" SET "children" = $1, "updated_at" = $2 WHERE "id" = $3 [[%{comment: "Basic Vocabulary", doc_id: 497, doc_identifier: "jxxcarlson.basic_vocabulary.2017-6-23@17:31:50.2a332f", id: "6510069c-b877-4983-a49f-cec0cf1687e9", level: 2, title: "Basic Vocabulary"}], {{2017, 7, 9}, {10, 8, 25, 350437}}, 495]
[info] Sent 500 in 48ms
[error] #PID<0.529.0> running Koko.Web.Endpoint terminated
Server: localhost:4000 (http)
Request: PUT /api/documents/495
** (exit) an exception was raised:
** (WithClauseError) no with clause matching: %Koko.DocManager.Document{__meta__: #Ecto.Schema.Metadata<:loaded, "documents">, attributes: %{"doc_type" => "master", "public" => true, "text_type" => "plain"}, author_id: 2, children: [%Child{comment: "Basic Vocabulary", doc_id: 497, doc_identifier: "jxxcarlson.basic_vocabulary.2017-6-23@17:31:50.2a332f", id: "6510069c-b877-4983-a49f-cec0cf1687e9", level: 2, title: "Basic Vocabulary"}], content: "== 496 // Introduction\n== 497 // Basic Vocabulary\n// test this\n\n\n", id: 495, identifier: "jxxcarlson.python_notes.2017-6-23@15:0:52.ec70e2", inserted_at: ~N[2017-06-23 15:00:52.328038], rendered_content: "== 496 // Introduction\n== 497 // Basic Vocabulary\n// test this\n\n\n", tags: [], title: "Python Notes", updated_at: ~N[2017-07-09 10:08:25.350437]}
(koko_web) lib/koko_web/controllers/document_controller.ex:123: Koko.Web.DocumentController.update/2
(koko_web) lib/koko_web/controllers/document_controller.ex:1: Koko.Web.DocumentController.action/2
(koko_web) lib/koko_web/controllers/document_controller.ex:1: Koko.Web.DocumentController.phoenix_controller_pipeline/2
(koko_web) lib/koko_web/endpoint.ex:1: Koko.Web.Endpoint.instrument/4
(phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
(koko_web) lib/koko_web/endpoint.ex:1: Koko.Web.Endpoint.plug_builder_call/2
(koko_web) lib/plug/debugger.ex:123: Koko.Web.Endpoint."call (overridable 3)"/2
(koko_web) lib/koko_web/endpoint.ex:1: Koko.Web.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /Users/carlson/dev/apps/koko_umbrella/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
(4) Note
If I do not have the , on_replace: :delete
phrase, the error message is
[error] #PID<0.656.0> running Koko.Web.Endpoint terminated
Server: localhost:4000 (http)
Request: PUT /api/documents/495
** (exit) an exception was raised:
** (RuntimeError) you are attempting to change relation :children of
Koko.DocManager.Document, but there is missing data.
If you are attempting to update an existing entry, please make sure
you include the entry primary key (ID) alongside the data.
If you have a relationship with many children, at least the same N
children must be given on update. By default it is not possible to
orphan embed nor associated records, attempting to do so results in
this error message.
If you don't desire the current behavior or if you are using embeds
without a primary key, it is possible to change this behaviour by
setting `:on_replace` when defining the relation. See `Ecto.Changeset`'s
section on related data for more info.
*(5) Note
I added @primary_key false
to the embedded schema. No change in error message.