Hello,
I am trying to cast data for which I specify types dynamically at runtime. In my particular case I’d like to validate that a single field is an array of string-keyed maps with single key/value both of which are strings, and the value should be one of a strict set of strings.
It’s about casting a standardised (in our company) sorting parameters passed to our Phoenix controllers.
The Phoenix parameters format goes like this:
%{
sort: [ %{"birthdate" => "desc"}, %{"inserted_at" => "asc"} ]
# all other parameters
}
(This is achieved by sending an HTTP query like so: ?sort[][birthdate]=desc&sort[][inserted_at]=asc
)
At the moment I am doing this:
fields = [:sort]
params = %{"sort" => [%{"birthdate" => "desc"}, %{"inserted_at" => "desc"}]}
types = %{sort: {:array, :map}}
Ecto.Changeset.cast({%{}, types}, params, fields)
And it works (meaning the resulting changeset is valid).
However, I wonder if there’s a way to achieve finer-grained control of the type of the sort
key. I blindly tried this: types = %{sort: {:array, {:map, :string}}}
and it also worked, but to be completely honest I have no idea why.
Is there a way to achieve this finer-grained type control when casting with Ecto’s Changeset? If so, where is it documented?