I am testing a function that builds and executes changesets. Using more direct methods, this changeset has functioned. In this case, I’m getting a very strange cast error that my map isn’t a map.
The changeset:
def changeset(prompt, attrs) do
IO.inspect(attrs, label: "Changeset Attrs")
prompt
|> IO.inspect(label: "Changeset Init")
|> cast(attrs, [:id, :short, :text])
|> validate_required([:id, :short, :text])
end
The error:
** (Ecto.CastError) expected params to be a :map, got: `%Prompt{__meta__: #Ecto.Schema.Metadata<:built, "prompts">, id: 1, short: "Short_A", text: "Gesture", program_id: nil, program: #Ecto.Association.NotLoaded<association :program is not loaded>, inserted_at: nil, updated_at: nil}`
(ecto 3.10.1) lib/ecto/changeset.ex:665: Ecto.Changeset.cast/4
(server 0.1.0) prompt.ex:21: Prompt.changeset/2
(server 0.1.0) lib/util.ex:11: anonymous fn/5 in Util.changeset_over_list/4
(elixir 1.14.2) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
The Inspect calls above reveal:
Changeset Attrs: %Prompt{
__meta__: #Ecto.Schema.Metadata<:built, "prompts">,
id: 1,
short: "Short_A",
text: "Gesture",
program_id: nil,
program: #Ecto.Association.NotLoaded<association :program is not loaded>,
inserted_at: nil,
updated_at: nil
}
Changeset Init: %Prompt{
__meta__: #Ecto.Schema.Metadata<:built, "prompts">,
id: 1,
short: nil,
text: nil,
program_id: nil,
program: #Ecto.Association.NotLoaded<association :program is not loaded>,
inserted_at: nil,
updated_at: nil
}
I honestly have no idea what’s going on here. I even tried guarding the inputs to ensure that maps are entering the changeset.
I may have hit some cornercase for cast, where the error and the message is mismatched but I’m not solid enough in elixir to detect what I could be doing wrong.
If it helps, here is the context where this is getting called:
def changeset_over_list(init_conds, updates, changeset_func, id_key \\ :id) do
Enum.reduce(updates, [], fn update, list ->
x =
get_item_by_id_key(init_conds, Map.get(update, id_key), id_key)
# |> IO.inspect(label: "Post Get Item By Key")
|> changeset_func.(update)
[x | list]
end)
end