Skip to content

Commit

Permalink
Fix Waffle.Ecto.Type load and dump in embeds
Browse files Browse the repository at this point in the history
- fixes elixir-waffle#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
  • Loading branch information
timadevelop committed Dec 12, 2022
1 parent 75f8710 commit 009571c
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/waffle_ecto/definition.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions lib/waffle_ecto/type.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
26 changes: 26 additions & 0 deletions test/type_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 009571c

Please sign in to comment.