Skip to content

Commit

Permalink
add support for ecto options in insert and insert! functions (izelnak…
Browse files Browse the repository at this point in the history
…ri#102)

Signed-off-by: Erik Hanson <[email protected]>

Co-authored-by: Harold Tafur <[email protected]>
  • Loading branch information
2 people authored and mayel committed Jun 26, 2023
1 parent ca58f72 commit bc226f3
Show file tree
Hide file tree
Showing 7 changed files with 78 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 @@ -31,7 +31,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 @@ -40,8 +40,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 @@ -67,13 +68,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
8 changes: 5 additions & 3 deletions lib/paper_trail/multi.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ defmodule PaperTrail.Multi do
originator: nil,
prefix: nil,
model_key: :model,
version_key: :version
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 @@ -55,7 +57,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} ->
Expand All @@ -66,7 +68,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 bc226f3

Please sign in to comment.