I have a String param coming from the client, but it should be a NaiveDateTime in my schema, because of that I am thinking about transforming it before passing it to the cast function, is it fine?
def changeset(my_struct, attrs) do
my_struct
|> my_transformation_func(attrs) # transform type string to NaiveDateTime
|> cast(attrs, [:my_date])
|> ...
end
Or maybe it is better to transform at the controller or context levels?
The Ecto.Changeset doc says:
The functions cast/4 and change/2 are the usual entry points for creating changesets.
Turning values from “external” shapes (like strings) to “application” shapes (like structs) is part of what Ecto.Changeset.cast does - it uses the fields declared in the schema to decide how to do that.
What does the input string look like? Standard shapes may “just work”, or you could define a custom Ecto.Type to do special parsing.
Oh, makes sense, but I didn’t find a place in the docs that says how string dates are cast into Elixir datatypes by Ecto.Changeset.cast, you know where it is?
In my case, my strings come from a select input and seem like this: 1-hour, 12-hour, 1-day, etc… I was trying to transform it into a NaiveDateTime by adding them to the current NaiveDateTime (doing some specific parsing).
A custom Ecto.Type may help me to parse it directly via cast as you said, but if standard shapes may just work I think it could be an easier way to reach the result.
There are at least a couple schools of thought on if/where to do this. a) parse/validate at the boundary (LiveVIew, controller, etc) and then pass structured data to your core. b) pass the user/api data straight through to your changeset functions.
Not sure I fully understand the interface but assuming that these are literals that will be transformed into actual date times, why not “let” the FE handle it using simple option labels/values?