In a validate method on phx-change, it’s common to Map.put(:action, :insert) to the changeset. This is obviously used somehow by the form function. I’m having a bit of trouble deciphering it, as I can’t figure out where the action is received from the for map/struct. Probably missed it, my eyes are still adjusting to elixir.
What specifically does this do and are there more values that are used by the .form function?
Per the links @cpgo supplied, generally speaking, the Phoenix HTML functions will not display errors for a changeset unless it has an action value, which usually is something Ecto will apply as part of a bad insert or update. If you are doing other more manual things with the changeset, you need to assign the action yourself to have an outcome where the form presents the errors as expected.
I think it is a mistake that the code you are looking at is editing the map directly. You should probably lean on the apply_action/2 function to avoid making assumptions about the underlying Changeset map structure.
While I generally support your suggestion there‘s also nothing wrong with depending on the changeset structure, which is publicly documented and not going to change (in a breaking way) without a mayor version bump of ecto.
Just wanted to note here that the official docs say it’s ok to update directly:
Ecto automatically applies the action for you when you call Repo.insert/update/delete, but if you want to show errors manually you can also set the action yourself, either directly on the Ecto.Changeset struct field or by using Ecto.Changeset.apply_action/2 .
(Emphasis mine.)
Probably explains why the generators use this pattern in live views:
defp validate_thing(socket, thing_params) do
changeset =
socket.assigns.thing
|> Things.change(thing_params)
|> Map.put(:action, :validate)
assign(socket, :changeset, changeset)
end