From bc9f39bb908d23c844c40a569e210569b704b3dc Mon Sep 17 00:00:00 2001 From: Rafael Scheffer Date: Thu, 24 Sep 2020 11:29:07 -0300 Subject: [PATCH] Support serializing embeddeds (#7) --- lib/paper_trail/serializer.ex | 16 +++++---- .../20160619190937_add_simple_companies.exs | 1 + .../bang_functions_simple_mode_test.exs | 30 +++++++++++------ test/paper_trail/base_test.exs | 33 ++++++++++++------- test/support/simple_models.exs | 15 +++++++++ 5 files changed, 68 insertions(+), 27 deletions(-) diff --git a/lib/paper_trail/serializer.ex b/lib/paper_trail/serializer.ex index 5b1d34ec..5b150f82 100644 --- a/lib/paper_trail/serializer.ex +++ b/lib/paper_trail/serializer.ex @@ -130,12 +130,12 @@ defmodule PaperTrail.Serializer do changes = model |> Map.from_struct() |> Map.take(fields) schema - |> dump_fields!(changes, dumper, adapter) + |> dump_fields!(changes, dumper, adapter, options) |> Map.new() end - @spec dump_fields!(module, map, module, module) :: Keyword.t() - defp dump_fields!(schema, changes, dumper, adapter) do + @spec dump_fields!(module, map, module, module, options) :: Keyword.t() + defp dump_fields!(schema, changes, dumper, adapter, options) do for {field, value} <- changes do {alias, type} = Map.fetch!(dumper, field) @@ -143,15 +143,19 @@ defmodule PaperTrail.Serializer do if( type in ignored_ecto_types(), do: value, - else: dump_field!(schema, field, type, value, adapter) + else: dump_field!(schema, field, type, value, adapter, options) ) {alias, dumped_value} end end - @spec dump_field!(module, atom, atom, any, module) :: any - defp dump_field!(schema, field, type, value, adapter) do + @spec dump_field!(module, atom, atom, any, module, options) :: any + defp dump_field!(_schema, _field, _type, %Ecto.Changeset{} = value, _adapter, options) do + serialize_changes(value, options) + end + + defp dump_field!(schema, field, type, value, adapter, _options) do case Ecto.Type.adapter_dump(adapter, type, value) do {:ok, value} -> value diff --git a/priv/repo/migrations/20160619190937_add_simple_companies.exs b/priv/repo/migrations/20160619190937_add_simple_companies.exs index 36c78216..59dd77ca 100644 --- a/priv/repo/migrations/20160619190937_add_simple_companies.exs +++ b/priv/repo/migrations/20160619190937_add_simple_companies.exs @@ -12,6 +12,7 @@ defmodule Repo.Migrations.CreateSimpleCompanies do add :twitter, :string add :founded_in, :string add :location, :map + add :email_options, :map timestamps() end diff --git a/test/paper_trail/bang_functions_simple_mode_test.exs b/test/paper_trail/bang_functions_simple_mode_test.exs index b3ab1d9a..4a4ca736 100644 --- a/test/paper_trail/bang_functions_simple_mode_test.exs +++ b/test/paper_trail/bang_functions_simple_mode_test.exs @@ -62,7 +62,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: nil, twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -113,7 +114,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -163,7 +165,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -222,7 +225,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -242,7 +246,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil }), originator_id: user.id, origin: nil, @@ -491,7 +496,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: nil, twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -548,7 +554,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -605,7 +612,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -674,7 +682,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -694,7 +703,8 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: nil + location: nil, + email_options: nil }), originator_id: user.id, origin: nil, diff --git a/test/paper_trail/base_test.exs b/test/paper_trail/base_test.exs index ae09d500..70e50e29 100644 --- a/test/paper_trail/base_test.exs +++ b/test/paper_trail/base_test.exs @@ -13,13 +13,15 @@ defmodule PaperTrailTest do name: "Acme LLC", is_active: true, city: "Greenwich", - location: %{country: "Brazil"} + location: %{country: "Brazil"}, + email_options: %{newsletter_enabled: false} } @update_company_params %{ city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc", - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} } defmodule CustomPaperTrail do @@ -73,7 +75,8 @@ defmodule PaperTrailTest do facebook: nil, twitter: nil, founded_in: nil, - location: %{country: "Brazil"} + location: %{country: "Brazil"}, + email_options: %{newsletter_enabled: false} } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -141,7 +144,8 @@ defmodule PaperTrailTest do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -152,7 +156,8 @@ defmodule PaperTrailTest do city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc", - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} }, originator_id: user.id, origin: nil, @@ -192,7 +197,8 @@ defmodule PaperTrailTest do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -203,7 +209,8 @@ defmodule PaperTrailTest do city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc", - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} }, originator_id: user.id, origin: nil, @@ -263,7 +270,8 @@ defmodule PaperTrailTest do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -282,7 +290,8 @@ defmodule PaperTrailTest do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} }, originator_id: user.id, origin: nil, @@ -320,7 +329,8 @@ defmodule PaperTrailTest do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} } assert Map.drop(version, [:id, :inserted_at]) == %{ @@ -339,7 +349,8 @@ defmodule PaperTrailTest do facebook: "acme.llc", twitter: nil, founded_in: nil, - location: %{country: "Chile"} + location: %{country: "Chile"}, + email_options: %{newsletter_enabled: true} }, originator_id: user.id, origin: nil, diff --git a/test/support/simple_models.exs b/test/support/simple_models.exs index 02b350d0..9132d28f 100644 --- a/test/support/simple_models.exs +++ b/test/support/simple_models.exs @@ -23,6 +23,19 @@ defmodule LocationType do def dump(_), do: :error end +defmodule EmailOptions do + use Ecto.Schema + + @primary_key false + embedded_schema do + field(:newsletter_enabled, :boolean) + end + + def changeset(options, params) do + Ecto.Changeset.cast(options, params, [:newsletter_enabled]) + end +end + defmodule SimpleCompany do use Ecto.Schema @@ -41,6 +54,7 @@ defmodule SimpleCompany do field(:twitter, :string) field(:founded_in, :string) field(:location, LocationType) + embeds_one(:email_options, EmailOptions, on_replace: :update) has_many(:people, SimplePerson, foreign_key: :company_id) @@ -62,6 +76,7 @@ defmodule SimpleCompany do def changeset(model, params \\ %{}) do model |> cast(params, @optional_fields) + |> cast_embed(:email_options, with: &EmailOptions.changeset/2) |> validate_required([:name]) |> no_assoc_constraint(:people) end