From 009571c58de35afb92552c30e3730860eab12371 Mon Sep 17 00:00:00 2001 From: timadevelop Date: Mon, 12 Dec 2022 11:15:40 +0200 Subject: [PATCH] Fix Waffle.Ecto.Type load and dump in embeds - fixes elixir-waffle/waffle_ecto#19 By default Ecto uses :self strategy which encodes the type without calling load/1 or dump/1 on custom type. So Waffle.Ecto.Type was encoded and decoded as a json, with native Ecto tools -> it was stored as an actual json in DB instead of using `filename_with_timestamp` string representation defined in Waffle.Ecto.Type BREAKING CHANGE: this commit will "break" loading existing embedded fieds from DB that used previous waffle versions. Now Waffle.Ecto.Type expects `value` to be a string, but old representation will feed it a map. Depending on your ecto adapter, you can fix it by: a) re-dumping all values to your db properly b) adding Waffle.Ecto.Type.load/2 for a json Map values and parsing "updated_at" map value to NaiveDateTime from a representation specific to your adapter --- lib/waffle_ecto/definition.ex | 1 + lib/waffle_ecto/type.ex | 2 ++ test/type_test.exs | 26 ++++++++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/lib/waffle_ecto/definition.ex b/lib/waffle_ecto/definition.ex index ad67006..94d64fa 100644 --- a/lib/waffle_ecto/definition.ex +++ b/lib/waffle_ecto/definition.ex @@ -56,6 +56,7 @@ defmodule Waffle.Ecto.Definition do def cast(value), do: Waffle.Ecto.Type.cast(unquote(definition), value) def load(value), do: Waffle.Ecto.Type.load(unquote(definition), value) def dump(value), do: Waffle.Ecto.Type.dump(unquote(definition), value) + def embed_as(format), do: Waffle.Ecto.Type.embed_as(unquote(definition), format) end def url({%{file_name: file_name, updated_at: updated_at}, scope}, version, options) do diff --git a/lib/waffle_ecto/type.ex b/lib/waffle_ecto/type.ex index c2df878..09a40e9 100644 --- a/lib/waffle_ecto/type.ex +++ b/lib/waffle_ecto/type.ex @@ -72,5 +72,7 @@ defmodule Waffle.Ecto.Type do dump(definition, %{file_name: file_name, updated_at: updated_at}) end + def embed_as(_definition, _format), do: :dump + defp log_error(error), do: Logger.error(inspect(error)) end diff --git a/test/type_test.exs b/test/type_test.exs index 25d1eb2..4ae90ab 100644 --- a/test/type_test.exs +++ b/test/type_test.exs @@ -37,4 +37,30 @@ defmodule WaffleTest.Ecto.Type do {:ok, dumped_type} = DummyDefinition.Type.dump(value) assert dumped_type == "file.png" end + + test "dumps as embedded type to a string" do + timestamp = NaiveDateTime.from_erl!({{1970, 1, 1}, {0, 0, 0}}) + + assert {:ok, value} = + Ecto.Type.embedded_dump( + DummyDefinition.Type, + %{file_name: "file.png", updated_at: timestamp}, + :json + ) + + assert value == "file.png?62167219200" + end + + test "loads as embedded type from a string" do + timestamp = NaiveDateTime.from_erl!({{1970, 1, 1}, {0, 0, 0}}) + + assert {:ok, value} = + Ecto.Type.embedded_load( + DummyDefinition.Type, + "file.png?62167219200", + :json + ) + + assert value == %{file_name: "file.png", updated_at: timestamp} + end end