Thank you, the library looks nice. It does not fit out needs though as if JSONb column has type information it’s trivial to make it polymorphic without any external libraries (just pattern match on load in specific type).
Our cast is different, in the raw Ecto schema we have a type
field and then payload
field which should be casted depending on type
field value. Which Ecto does not allow as you can’t access type
value while casting/dumpin/loading payload
field.
Here is our implementation: https://gist.github.com/AndrewDryga/72f2cdd366265afb4c0528935fa96927. It’s used in production and did not cause any issues yet. It’s very hacky though.
Notice that we explicitly call load_dynamic_embed/2
function every time schema is loaded from DB. We also dump everything to string-keyed map if changeset is valid to mimic behaviour of writing and reading from DB (so that you can compare user == inserted_user
in test cases, otherwise string- and atom-keyed maps would be a problem).
If embedded changeset has an error it looks very much like nested schema was defined by using embeds_one/many`.
Why not just copy the type
field into the payload? You could do that in the changeset, before calling cast of a custom type.
I suggested to copy the type field, so you end up with the exact same structure in the DB, no difference for querying, i.e. a type and payload fields in the schema, in addition to a type in the payload to enable polymorphism. That small logic for copying the type would be done in the changeset.
Resorting to non documented, private internals such as Ecto.Embedded
struct and its fields (thus that might change and break your app) seems worse as a solution. Would you go for a minor weirdness, or a fragile hack?
Indeed I don’t know about the limitations you faced back in 2018, as I wasn’t doing Elixir at that time.
I see however that ecto_poly was released end 2017, so there were some possibilities.
1 Like