From 95a7ef2ab2c645b0f2d45fa07aada58eb87d1671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Pr=C3=A1?= Date: Mon, 9 Sep 2019 19:27:07 -0300 Subject: [PATCH] Support delete with changeset (#59) --- .gitignore | 1 + lib/paper_trail.ex | 21 ++++++++++----- test/paper_trail_test.exs | 55 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 755b6055..dcc1bebe 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /deps erl_crash.dump *.ez +.elixir_ls diff --git a/lib/paper_trail.ex b/lib/paper_trail.ex index 1a0a6fb6..d862dae7 100644 --- a/lib/paper_trail.ex +++ b/lib/paper_trail.ex @@ -278,7 +278,7 @@ defmodule PaperTrail do %Version{ event: "insert", - item_type: model.__struct__ |> Module.split() |> List.last(), + item_type: get_item_type(model), item_id: get_model_id(model), item_changes: serialize(model), originator_id: @@ -298,8 +298,8 @@ defmodule PaperTrail do %Version{ event: "update", - item_type: changeset.data.__struct__ |> Module.split() |> List.last(), - item_id: get_model_id(changeset.data), + item_type: get_item_type(changeset), + item_id: get_model_id(changeset), item_changes: changeset.changes, originator_id: case originator_ref do @@ -312,15 +312,15 @@ defmodule PaperTrail do |> add_prefix(options[:prefix]) end - defp make_version_struct(%{event: "delete"}, model, options) do + defp make_version_struct(%{event: "delete"}, model_or_changeset, options) do originator = PaperTrail.RepoClient.originator() originator_ref = options[originator[:name]] || options[:originator] %Version{ event: "delete", - item_type: model.__struct__ |> Module.split() |> List.last(), - item_id: get_model_id(model), - item_changes: serialize(model), + item_type: get_item_type(model_or_changeset), + item_id: get_model_id(model_or_changeset), + item_changes: serialize(model_or_changeset), originator_id: case originator_ref do nil -> nil @@ -348,6 +348,8 @@ defmodule PaperTrail do |> List.first() end + defp serialize(%Ecto.Changeset{data: data}), do: serialize(data) + defp serialize(model) do relationships = model.__struct__.__schema__(:associations) Map.drop(model, [:__struct__, :__meta__] ++ relationships) @@ -356,6 +358,11 @@ defmodule PaperTrail do defp add_prefix(changeset, nil), do: changeset defp add_prefix(changeset, prefix), do: Ecto.put_meta(changeset, prefix: prefix) + defp get_item_type(%Ecto.Changeset{data: data}), do: get_item_type(data) + defp get_item_type(model), do: model.__struct__ |> Module.split() |> List.last() + + def get_model_id(%Ecto.Changeset{data: data}), do: get_model_id(data) + def get_model_id(model) do {_, model_id} = List.first(Ecto.primary_key(model)) diff --git a/test/paper_trail_test.exs b/test/paper_trail_test.exs index 1200ac21..4480f3be 100644 --- a/test/paper_trail_test.exs +++ b/test/paper_trail_test.exs @@ -262,6 +262,61 @@ defmodule PaperTrailTest do assert company == company_before_deletion end + test "delete works with a changeset" do + user = create_user() + {:ok, insert_result} = create_company_with_version() + {:ok, update_result} = update_company_with_version(insert_result[:model]) + company_before_deletion = first(Company, :id) |> @repo.one + + changeset = Company.changeset(company_before_deletion, %{}) + {:ok, result} = PaperTrail.delete(changeset, originator: user) + + company_count = Company.count() + version_count = Version.count() + + company = result[:model] |> serialize + version = result[:version] |> serialize + + assert Map.keys(result) == [:model, :version] + assert company_count == 0 + assert version_count == 3 + + assert Map.drop(company, [:id, :inserted_at, :updated_at]) == %{ + name: "Acme LLC", + is_active: true, + city: "Hong Kong", + website: "http://www.acme.com", + address: nil, + facebook: "acme.llc", + twitter: nil, + founded_in: nil + } + + assert Map.drop(version, [:id, :inserted_at]) == %{ + event: "delete", + item_type: "SimpleCompany", + item_id: company.id, + item_changes: %{ + id: company.id, + inserted_at: company.inserted_at, + updated_at: company.updated_at, + name: "Acme LLC", + is_active: true, + website: "http://www.acme.com", + city: "Hong Kong", + address: nil, + facebook: "acme.llc", + twitter: nil, + founded_in: nil + }, + originator_id: user.id, + origin: nil, + meta: nil + } + + assert company == serialize(company_before_deletion) + end + test "PaperTrail.delete/2 with an error returns and error tuple like Repo.delete/2" do {:ok, insert_company_result} = create_company_with_version()