How to validate dynamic fields in embedded_schema

Changesets work with atom keys, so they’re inherently unfit for dynamic validations, as converting user data to atoms (field names) is essentially a DOS vector on the beam. There are a few ways around that:

  • Validate each field on it’s own using a generic key like :field in the changeset. This works well for validation, but not for passing errors back to e.g. a phoenix form.
  • Same as above, but implement Phoenix.HTML.FormData for a custom struct, which stores information like errors.
  • Mapping string field names to a fixed set of atom keys you control. This way you have the best of both worlds. Atoms for the changeset and still string keys for your setup, but you need to map between both representations. I’ve gone this route for my use-case and just wrapped all the mapping logic in a struct, which holds all the necessary data and the resulting changeset.
  • Implement FormData and validation custom. Maybe there are even validation libraries out there being able to work with string keyed data.

If you have atom keys or you’re not worried about converting strings to atoms then you can look into schemaless changeset, which are actually quite simple to use. I’d suggest the “what’s new in ecto 2” ebook for more information on those.

Edit: Also try to not nest those dynamic data as this makes things even more complex. Rather validate things in multiple steps and put dynamic fields at the root level of your forms.

4 Likes