From e4c56ce1af0c63c0524ffd8b002681d8dadda345 Mon Sep 17 00:00:00 2001 From: Rafael Scheffer Date: Mon, 15 Feb 2021 10:48:52 -0300 Subject: [PATCH] Do not create version when there are no changes (#11) --- lib/paper_trail.ex | 21 +++++++++++---------- lib/paper_trail/multi.ex | 12 +++++++++--- test/paper_trail/base_test.exs | 23 +++++++++++++++++++++++ 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/lib/paper_trail.ex b/lib/paper_trail.ex index 2dec0e10..09d36092 100644 --- a/lib/paper_trail.ex +++ b/lib/paper_trail.ex @@ -1,6 +1,7 @@ defmodule PaperTrail do import Ecto.Changeset + alias Ecto.Changeset alias PaperTrail.Multi alias PaperTrail.RepoClient alias PaperTrail.Serializer @@ -32,16 +33,16 @@ defmodule PaperTrail do returning: boolean() ] - @type result :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()} + @type result :: {:ok, Ecto.Schema.t()} | {:error, Changeset.t()} @type all_result :: {integer, nil | [any]} - @callback insert(Ecto.Changeset.t(), options) :: result - @callback insert!(Ecto.Changeset.t(), options) :: Ecto.Schema.t() - @callback update(Ecto.Changeset.t(), options) :: result - @callback update!(Ecto.Changeset.t(), options) :: Ecto.Schema.t() + @callback insert(Changeset.t(), options) :: result + @callback insert!(Changeset.t(), options) :: Ecto.Schema.t() + @callback update(Changeset.t(), options) :: result + @callback update!(Changeset.t(), options) :: Ecto.Schema.t() @callback update_all(queryable, updates, options) :: all_result - @callback delete(Ecto.Changeset.t(), options) :: result - @callback delete!(Ecto.Changeset.t(), options) :: Ecto.Schema.t() + @callback delete(Changeset.t(), options) :: result + @callback delete!(Changeset.t(), options) :: Ecto.Schema.t() @callback get_version(Ecto.Schema.t()) :: Ecto.Query.t() @callback get_version(module, any) :: Ecto.Query.t() @@ -172,7 +173,7 @@ defmodule PaperTrail do @doc """ Inserts a record to the database with a related version insertion in one transaction """ - @spec insert(Ecto.Changeset.t(), options) :: result + @spec insert(Changeset.t(), options) :: result def insert(changeset, options \\ []) do Multi.new() |> Multi.insert(changeset, options) @@ -230,7 +231,7 @@ defmodule PaperTrail do @doc """ Updates a record from the database with a related version insertion in one transaction """ - @spec update(Ecto.Changeset.t(), options) :: result + @spec update(Changeset.t(), options) :: result def update(changeset, options \\ []) do Multi.new() |> Multi.update(changeset, options) @@ -292,7 +293,7 @@ defmodule PaperTrail do @doc """ Deletes a record from the database with a related version insertion in one transaction """ - @spec delete(Ecto.Changeset.t(), options) :: result + @spec delete(Changeset.t(), options) :: result def delete(struct, options \\ []) do Multi.new() |> Multi.delete(struct, options) diff --git a/lib/paper_trail/multi.ex b/lib/paper_trail/multi.ex index e4ae6548..6a5bf64e 100644 --- a/lib/paper_trail/multi.ex +++ b/lib/paper_trail/multi.ex @@ -1,17 +1,18 @@ defmodule PaperTrail.Multi do import Ecto.Changeset + alias Ecto.Changeset alias PaperTrail alias PaperTrail.Version alias PaperTrail.RepoClient alias PaperTrail.Serializer @type multi :: Ecto.Multi.t() - @type changeset :: Ecto.Changeset.t() + @type changeset :: Changeset.t() @type options :: PaperTrail.options() @type queryable :: PaperTrail.queryable() @type updates :: PaperTrail.updates() - @type struct_or_changeset :: Ecto.Schema.t() | Ecto.Changeset.t() + @type struct_or_changeset :: Ecto.Schema.t() | Changeset.t() @type result :: {:ok, any()} | {:error, any()} @@ -133,7 +134,12 @@ defmodule PaperTrail.Multi do |> Ecto.Multi.update(model_key, changeset) |> Ecto.Multi.run(version_key, fn repo, _changes -> version = make_version_struct(%{event: "update"}, changeset, options) - repo.insert(version) + + if changeset.changes == %{} do + {:ok, nil} + else + repo.insert(version) + end end) end end diff --git a/test/paper_trail/base_test.exs b/test/paper_trail/base_test.exs index ef6eded7..025c3667 100644 --- a/test/paper_trail/base_test.exs +++ b/test/paper_trail/base_test.exs @@ -167,6 +167,29 @@ defmodule PaperTrailTest do assert company == first(Company, :id) |> @repo.one |> serialize end + test "do not create version if there're no changes" do + {:ok, insert_result} = create_company_with_version() + + {:ok, result} = + update_company_with_version( + insert_result[:model], + %{} + ) + + company_count = Company.count() + version_count = Version.count() + + company = result[:model] |> serialize + version = result[:version] + + assert Map.keys(result) == [:model, :version] + assert company_count == 1 + assert version_count == 1 + + assert company == insert_result[:model] |> serialize + assert version == nil + end + test "updating a company with originator[user] creates a correct company version" do user = create_user() {:ok, insert_result} = create_company_with_version()