Skip to content

Commit

Permalink
Support serializing embeddeds (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
rschef authored Sep 24, 2020
1 parent 3f4f6f3 commit bc9f39b
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 27 deletions.
16 changes: 10 additions & 6 deletions lib/paper_trail/serializer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -130,28 +130,32 @@ 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)

dumped_value =
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 20 additions & 10 deletions test/paper_trail/bang_functions_simple_mode_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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]) == %{
Expand Down Expand Up @@ -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]) == %{
Expand Down Expand Up @@ -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]) == %{
Expand Down Expand Up @@ -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]) == %{
Expand All @@ -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,
Expand Down Expand Up @@ -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]) == %{
Expand Down Expand Up @@ -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]) == %{
Expand Down Expand Up @@ -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]) == %{
Expand Down Expand Up @@ -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]) == %{
Expand All @@ -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,
Expand Down
33 changes: 22 additions & 11 deletions test/paper_trail/base_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]) == %{
Expand Down Expand Up @@ -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]) == %{
Expand All @@ -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,
Expand Down Expand Up @@ -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]) == %{
Expand All @@ -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,
Expand Down Expand Up @@ -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]) == %{
Expand All @@ -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,
Expand Down Expand Up @@ -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]) == %{
Expand All @@ -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,
Expand Down
15 changes: 15 additions & 0 deletions test/support/simple_models.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)

Expand All @@ -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
Expand Down

0 comments on commit bc9f39b

Please sign in to comment.