embeds_many
リレーションシップを持つモデルを更新しようとすると、Phoenixアプリケーションでno function clause matching in Ecto.Changeset.change/2
エラーが発生します。私はドキュメントを読んでこれについての他の投稿を見ましたが、私が間違っていることを理解することはできません。embeds_manyレコードの更新時にPhoenix/Ecto - チェンジセットエラーが発生しました
まず第一に、ここでエラーがあります:
** (FunctionClauseError) no function clause matching in Ecto.Changeset.change/2
(ecto) lib/ecto/changeset.ex:307: Ecto.Changeset.change(%{"content" => "<p>Nice to see you</p>", "duration" => 15, "id" => "93387d2d-a6ed-4902-911f-4dc1525aca2b"}, %{})
(ecto) lib/ecto/changeset/relation.ex:196: Ecto.Changeset.Relation.on_replace/2
(ecto) lib/ecto/changeset/relation.ex:299: Ecto.Changeset.Relation.reduce_delete_changesets/5
(ecto) lib/ecto/changeset.ex:691: Ecto.Changeset.cast_relation/4
(myapp) web/models/agenda.ex:20: MyApp.Agenda.changeset/2
'親' モデルはAgenda
であり、組み込みモデルがAgendaPage
です。次のようなモデルが定義されています。
agenda.ex
defmodule MyApp.Agenda do
use MyApp.Web, :model
@primary_key {:id, :string, []}
@derive {Phoenix.Param, key: :id}
schema "agenda" do
field :name, :string
embeds_many :pages, MyApp.AgendaPage, on_replace: :delete
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name])
|> cast_embed(:pages)
|> validate_required([:name])
end
end
agenda_page.ex
defmodule MyApp.AgendaPage do
use MyApp.Web, :model
embedded_schema do
field :content, :string
field :duration, :integer
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:content, :duration])
end
end
そしてiex
の端末でagenda_controller.ex
def update(conn, %{"id" => id, "agenda" => agenda_params}) do
agenda = Repo.get!(Agenda, id)
changeset = Agenda.changeset(agenda, agenda_params)
case Repo.update(changeset) do
{:ok, agenda} ->
json conn, %{status: "ok", agenda: agenda}
{:error, changeset} ->
errors = parse_errors(changeset)
IO.inspect errors
json(conn |> put_status(400), %{status: "error", message: "Failed to update Agenda", errors: errors})
end
end
からupdate
アクションを、私はEにアクセスすることができます以下のレコードをバック与えMyApp.Repo.get(MyApp.Agenda, "default_agenda")
とxistingの議題、:
%MyApp.Agenda{__meta__: #Ecto.Schema.Metadata<:built, "agenda">,
id: "default_agenda", name: "Default Agenda",
pages: [%{"content" => "<p>This is the default agenda</p>", "duration" => 10,
"id" => "0849862a-0794-4466-88a3-6052da360ca0"},
%{"content" => "<p>Nice to see you</p>", "duration" => 15,
"id" => "93387d2d-a6ed-4902-911f-4dc1525aca2b"}]}
コントローラのアクションでチェンジに渡されるagenda_params
の例は次のようになります。
%{
"id" => "default_agenda",
"name" => "Default Agenda",
"pages" => [
%{
"content" => "<p>foo</p>",
"duration" => 10,
"id" => "0849862a-0794-4466-88a3-6052da360ca0"
},
%{
"content" => "<p>bar</p>",
"duration" => 15,
"id" => "93387d2d-a6ed-4902-911f-4dc1525aca2b"
}
]
}
しかし、実行しようとしていますこのデータは更新処理によってエラーになります。誰かが何かガイダンスを提供できますか?
はい、あなたは正しい - スキーマに問題があるように思われます。私は少しをバックトラックする必要があります、あなたの投稿を維持します。私は「id」の問題について勘違いをしましたが、わかりませんでした。スティーブ、あなたの男! – skwidbreth
スティーブ、あなたは正しい方向に私を指摘しましたが、私はそれを解決する方法を正確に把握しなければなりません。要するに、挿入されたレコードを取得すると、埋め込みモデルへの参照を保持していないということです。私は 'pages:[%{" MyApp .AgendaPage {"content" ...}。 「id」の問題も問題でしたが、これが大きな問題です。私は実際にはPostgresを使用していません - 実験的なDynamoDBアダプタを使用しています...その構造を保存する方法を理解する必要があります。 – skwidbreth
私は、チェンジセットに渡された最初の引数にモデル参照を手動で追加することによって、正常な更新を行うことができました。スティーブ、あなたの視点でおかげさまで100万ドル! – skwidbreth