How to get struct from map - elixir?

I think this approach is the right fit for me. It preserves Ecto’s type casting without relying on validations that feel out of place when loading from the DB. A changeset makes sense in the app-to-DB direction, but going the other way it’s redundant since the data has already passed validation (at least if Ecto is the only DB writer — otherwise falling back to a proper changeset is fine).

pry(2)> 
Ecto.Changeset.cast(struct(schema_module), params, schema_module.__schema__(:fields)) 
|> Ecto.Changeset.apply_changes()
%Mozek.V3.Orchestrator.Rule.Instance.RequestSchema{
  __meta__: #Ecto.Schema.Metadata<:built, "v3_rule_instance_requests">,
  id: 207,
  freshness_stat_id: 718,
  inserted_at: ~U[2025-08-22 11:34:45Z]
}

A utility function like this works well — it handles type casting and embeds (associations could be added similarly if needed):

@spec cast_to_struct(module(), map()) :: struct()
def cast_to_struct(schema_module, params) when is_atom(schema_module) and is_map(params) do
  unless has_changeset?(schema_module) do
    raise "Schema #{inspect(schema_module)} does not have a changeset/2 function"
  end

  fields = schema_module.__schema__(:fields) -- schema_module.__schema__(:embeds)

  struct(schema_module)
  |> Ecto.Changeset.cast(params, fields)
  |> then(fn cs ->
    Enum.reduce(schema_module.__schema__(:embeds), cs, fn embed, acc ->
      Ecto.Changeset.cast_embed(acc, embed)
    end)
  end)
  |> Ecto.Changeset.apply_changes()
end