I respectfully disagree with this whole proposal.
You semi-handwaved this solution but for me this is the right answer and one of those things I’m pretty religious about in my own code. We should be converting—ie casting—our data into a known shape before doing anything with it, and this is exactly what Changeset.cast provides us. This is especially important in a dynamic language.
For me, string keys mean “untrusted”. Using this definition, general application code should rarely ever have a need to set a string key (of course there are always exceptions).
Multiple changesets are generally encouraged by the framework. “Citation needed,” yes sorry I don’t have doc or discussion links atm, the best I can give right now is to look at the User schema generated by phx_gen_auth. I actually do prefer to keep a single changeset myself when possible (it’s not a hard rule) but it results in me writing functions like maybe_assign_slug/1 which are probably more complex than they need to be if I’d just use multiple changesets.
If you really want to do these things in the context, there is no harm in manipulating changesets in the context—changesets are kind of wild as they are having a strong presence in the web layer as well as the business layer.
Of course, you could also do stuff like this in the context:
def create_article(attrs) do
%Article{}
|> Article.changeset(attrs)
|> MyApp.ChangesetHelpers.assign_slug_from(:title) # module name for illustrative purposes :D
|> Repo.insert()
end
Finally, I think any promotion of the idea that mixing map key types is ok is a bad idea, again, especially in a dynamic language.






















