Can I somehow indicate in the schema that metrics will always have those three fields?
I like exploring codebase by its data structures.
If I stumble upon something like {:array, :map} I can’t see what struct is that. The compiler also doesn’t check if I use correct keys when I access metrics because they are free form maps.
Unfortunately virtual: true does not work with has_many or embeds_many. Defining custom type with all the logic of casting to DB format also seems like overkill. Do you have a better way of embedding structs as virtual fields in the schema?
If the type is only used virtually, you might get away with defining a custom type where actually load and dump are error-throwing no-ops, and only cast is implemented in a sensible way (like calling struct!/2).
alias Connect.Campaign.Starting
schema "campaigns" do
field :description, :string
embeds_many :startings, Starting
timestamps()
end
defmodule Connect.Campaign.Starting do
use Ecto.Schema
import Ecto.Changeset
alias Connect.Campaign.Starting
embedded_schema do
field :can_run, :boolean, default: true
field :day, :integer, default: 0
field :end_at, :time, default: ~T[20:00:00]
field :start_at, :time, default: ~T[08:00:00]
end
end
Thank you for your input.
Unfortunately, that solution persists :startings in the DB. I’d like not to persist it but virtual: true does not mix with embeds_many.
If I’m not mistaken, you can still use an embedded_schema without saving it to the database. Just don’t cast the field nor make it required when you generate changesets.
I had a similar problem this week, you might want to take a look at this topic:
You probably solved this a long time ago.
In my projects I deal with exactly your problem a lot.
In such cases I use virtual (embedded) models for user interaction (forms).
These virtual models are never persisted so they can implement embeds_many.
Once the virtual model (changeset) is valid and it’s time to persist it’s contents, then I transform the virtual model to the actual model which may implement {:array, :map}.