Skip to content

Commit

Permalink
add support for ecto options in insert and insert! functions (#102)
Browse files Browse the repository at this point in the history
Signed-off-by: Erik Hanson <[email protected]>

Co-authored-by: Harold Tafur <[email protected]>
  • Loading branch information
hdtafur and Harold Tafur committed Aug 30, 2020
1 parent 51d2e2f commit ddc7f91
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 7 deletions.
9 changes: 5 additions & 4 deletions lib/paper_trail.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ defmodule PaperTrail do
@doc """
Inserts a record to the database with a related version insertion in one transaction
"""
def insert(changeset, options \\ [origin: nil, meta: nil, originator: nil, prefix: nil, model_key: :model, version_key: :version]) do
def insert(changeset, options \\ [origin: nil, meta: nil, originator: nil, prefix: nil, model_key: :model, version_key: :version, ecto_options: []]) do
PaperTrail.Multi.new()
|> PaperTrail.Multi.insert(changeset, options)
|> PaperTrail.Multi.commit()
Expand All @@ -24,8 +24,9 @@ defmodule PaperTrail do
@doc """
Same as insert/2 but returns only the model struct or raises if the changeset is invalid.
"""
def insert!(changeset, options \\ [origin: nil, meta: nil, originator: nil, prefix: nil, model_key: :model, version_key: :version]) do
def insert!(changeset, options \\ [origin: nil, meta: nil, originator: nil, prefix: nil, model_key: :model, version_key: :version, ecto_options: []]) do
repo = RepoClient.repo()
ecto_options = options[:ecto_options] || []

repo.transaction(fn ->
case RepoClient.strict_mode() do
Expand All @@ -51,13 +52,13 @@ defmodule PaperTrail do
current_version_id: initial_version.id
})

model = repo.insert!(updated_changeset)
model = repo.insert!(updated_changeset, ecto_options)
target_version = make_version_struct(%{event: "insert"}, model, options) |> serialize()
Version.changeset(initial_version, target_version) |> repo.update!
model

_ ->
model = repo.insert!(changeset)
model = repo.insert!(changeset, ecto_options)
make_version_struct(%{event: "insert"}, model, options) |> repo.insert!
model
end
Expand Down
7 changes: 4 additions & 3 deletions lib/paper_trail/multi.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ defmodule PaperTrail.Multi do
defdelegate to_list(multi), to: Ecto.Multi

def insert(%Ecto.Multi{} = multi, changeset, options \\ [
origin: nil, meta: nil, originator: nil, prefix: nil, model_key: :model, version_key: :version
origin: nil, meta: nil, originator: nil, prefix: nil, model_key: :model, version_key: :version, ecto_options: []
]) do
model_key = options[:model_key] || :model
version_key = options[:version_key] || :version
ecto_options = options[:ecto_options] || []

case RepoClient.strict_mode() do
true ->
Expand All @@ -46,7 +47,7 @@ defmodule PaperTrail.Multi do
current_version_id: initial_version.id
})

repo.insert(updated_changeset)
repo.insert(updated_changeset, ecto_options)
end)
|> Ecto.Multi.run(version_key, fn repo, %{initial_version: initial_version, model: model} ->
target_version = make_version_struct(%{event: "insert"}, model, options) |> serialize()
Expand All @@ -56,7 +57,7 @@ defmodule PaperTrail.Multi do

_ ->
multi
|> Ecto.Multi.insert(model_key, changeset)
|> Ecto.Multi.insert(model_key, changeset, ecto_options)
|> Ecto.Multi.run(version_key, fn repo, %{^model_key => model} ->
version = make_version_struct(%{event: "insert"}, model, options)
repo.insert(version)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule PaperTrail.Repo.Migrations.AddUniquenessConstraintToCompaniesName do
use Ecto.Migration

def change do
create unique_index(:simple_companies, [:name])
create unique_index(:strict_companies, [:name])
end
end
15 changes: 15 additions & 0 deletions test/paper_trail/bang_functions_simple_mode_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ defmodule PaperTrailTest.SimpleModeBangFunctions do
end)
end

test "PaperTrail.insert!/2 passes ecto options through (e.g. upsert options)" do
user = create_user()
_result = create_company_with_version(@create_company_params, [originator: user])

new_create_company_params = @create_company_params |> Map.replace!(:city, "Barcelona")

ecto_options = [on_conflict: {:replace_all_except, ~w{name}a}, conflict_target: :name]
result = create_company_with_version(new_create_company_params, [originator: user, ecto_options: ecto_options])

assert Company.count() == 1
assert Version.count() == 2

assert Map.take(serialize(result), [:name, :city]) == %{name: "Acme LLC", city: "Barcelona"}
end

test "updating a company with originator creates a correct company version" do
user = create_user()
inserted_company = create_company_with_version()
Expand Down
15 changes: 15 additions & 0 deletions test/paper_trail/bang_functions_strict_mode_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ defmodule PaperTrailTest.StrictModeBangFunctions do
end)
end

test "PaperTrail.insert!/2 passes ecto options through (e.g. upsert options)" do
user = create_user()
_result = create_company_with_version(@create_company_params, [originator: user])

new_create_company_params = @create_company_params |> Map.replace!(:city, "Barcelona")

ecto_options = [on_conflict: {:replace_all_except, ~w{name}a}, conflict_target: :name]
result = create_company_with_version(new_create_company_params, [originator: user, ecto_options: ecto_options])

assert Company.count() == 1
assert Version.count() == 2

assert Map.take(serialize(result), [:name, :city]) == %{name: "Acme LLC", city: "Barcelona"}
end

test "updating a company creates a company version with correct item_changes" do
user = create_user()
inserted_company = create_company_with_version()
Expand Down
15 changes: 15 additions & 0 deletions test/paper_trail/base_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ defmodule PaperTrailTest do
assert result == ecto_result
end

test "PaperTrail.insert/2 passes ecto options through (e.g. upsert options)" do
user = create_user()
{:ok, _result} = create_company_with_version(@create_company_params, [originator: user])

new_create_company_params = @create_company_params |> Map.replace!(:city, "Barcelona")

ecto_options = [on_conflict: {:replace_all_except, ~w{name}a}, conflict_target: :name]
{:ok, result} = create_company_with_version(new_create_company_params, [originator: user, ecto_options: ecto_options])

assert Company.count() == 1
assert Version.count() == 2

assert Map.take(serialize(result[:model]), [:name, :city]) == %{name: "Acme LLC", city: "Barcelona"}
end

test "updating a company with originator creates a correct company version" do
user = create_user()
{:ok, insert_result} = create_company_with_version()
Expand Down
15 changes: 15 additions & 0 deletions test/paper_trail/strict_mode_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@ defmodule PaperTrailStrictModeTest do
assert result == ecto_result
end

test "PaperTrail.insert/2 passes ecto options through (e.g. upsert options)" do
user = create_user()
{:ok, _result} = create_company_with_version(@create_company_params, [originator: user])

new_create_company_params = @create_company_params |> Map.replace!(:city, "Barcelona")

ecto_options = [on_conflict: {:replace_all_except, ~w{name}a}, conflict_target: :name]
{:ok, result} = create_company_with_version(new_create_company_params, [originator: user, ecto_options: ecto_options])

assert Company.count() == 1
assert Version.count() == 2

assert Map.take(serialize(result[:model]), [:name, :city]) == %{name: "Acme LLC", city: "Barcelona"}
end

test "updating a company creates a company version with correct item_changes" do
user = create_user()
{:ok, insert_company_result} = create_company_with_version()
Expand Down

0 comments on commit ddc7f91

Please sign in to comment.