Hello. I’m working on a caching library that reads and writes Ecto records to Memcached and I’m running into issues with “loading” the record.
Here’s the code I’m using:
Ecto.Repo.Schema.load(Ecto.Adapters.Postgres, schema, attributes)
Where schema is something like User
and attributes is a map.
The problem is that attributes is loaded from JSON, which means values from datetimes (like created_at) are strings like “2017-02-19T19:55:52.059727Z” and then the function fails.
I know I can make my own custom type and define a dump/load function, but that seems pretty invasive and a bit disingenuous (Ecto isn’t using the custom type, my caching library is).
Does anyone have any tips or tricks to solve this? Thank you.
1 Like
For posterity, here’s what I ended up doing…
def instantiate(schema, attributes) do
source = schema.__schema__(:source)
prefix = schema.__schema__(:prefix)
attributes = Poison.decode!(attributes)
Ecto.Schema.__load__(schema, prefix, source, nil, attributes, &custom_loader(&1, &2))
end
defp custom_loader(_, nil), do: {:ok, nil}
defp custom_loader(:utc_datetime, value) do
case DateTime.from_iso8601(value) do
{:ok, datetime, _offset} -> {:ok, datetime}
{:error, _reason} -> :error
end
end
defp custom_loader(:date, value) do
case Date.from_iso8601(value) do
{:ok, date} -> {:ok, date}
{:error, _reason} -> :error
end
end
defp custom_loader(type, value) do
Ecto.Type.adapter_load(Ecto.Adapters.Postgres, type, value)
end
Works like a charm.
1 Like