Closed yordis closed 1 year ago
This behaviour is pretty old and was added here: https://github.com/elixir-ecto/ecto/commit/1b224d19126fc26950f0185ddf204ce2245bd490
I believe it behaves this way because standard structs would make it impossible to differentiate when the field wasn't sent from when it was sent as nil, while with maps this is trivial.
Correct. No plans to change this at the moment but you can always call Map.from_struct before. :)
I believe it behaves this way because standard structs would make it impossible to differentiate when the field wasn't sent from when it was sent as nil, while with maps this is trivial.
@v0idpwn that went over my head, do you mind sharing a bit more about it? I would love to understand a bit more.
Assume we are updating the following schema: %Person{name: "John Doe", age: 30}
, and you want to update the age to 31.
We can receive the following attrs: %{age: 31}
. :name
is not a key and isn't considered changed in the changeset, thus is not updated.
Now, assume we receive %{age: 31, name: nil}
. This time, :name
is being changed and will be set to nil
in the database.
The thing with structs is that they have all the keys, so if you had the following struct:
defmodule UserAttrs do
defstruct [:name, :age]
end
You wouldn't be able to represent the situation where the name
isn't sent. If you do %UserAttrs{age: 31}
its equivalent to %UserAttrs{age: 31, name: nil}
.
Thank you so much for the extra context. I can see the potential problem now.
Although it makes sense if somebody is passing Map/Struct and you cast
the value, I wouldn't expect much magic. If the value is nil,
the new value is nil.
At some point, people must understand their data flow.
Being said, a problem for another day. For now, the workaround is acceptable đŸ˜„
Elixir version
Elixir 1.14.4
Database and Version
PostgresSQL 15
Ecto Versions
3.9.5
Database Adapter and Versions (postgrex, myxql, etc)
postgrex 0.16.5
Current behavior
We are leveraging Ecto Schemas and Changesets to validate Phoenix Parameters to ensure the "correctness" of the information at the Web/App level before passing it to other parts of the systems.
Here is my controller:
That is not the only place where we need to do this, we face these situations in other places as well, and we have to map all the keys to a
map
to avoid this issue.Expected behavior
Be able to pass a struct to
Ecto.Changeset.cast/4
function.