Skip to content

Commit

Permalink
simple paper trail tests done for stict_mode
Browse files Browse the repository at this point in the history
  • Loading branch information
izelnakri committed Mar 13, 2017
1 parent 263ebe9 commit 711404d
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 57 deletions.
1 change: 1 addition & 0 deletions lib/mix/tasks/papertrail/install.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ defmodule Mix.Tasks.Papertrail.Install do
# Uncomment if you want to add the following indexes to speed up special queries:
# create index(:versions, [:item_id, :item_type])
# create index(:versions, [:event, :item_type])
# create index(:versions, [:item_type, :inserted_at])
end
end
"""
Expand Down
101 changes: 66 additions & 35 deletions lib/paper_trail.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,36 +50,46 @@ defmodule PaperTrail do
def insert(changeset, options \\ [sourced_by: nil, meta: nil]) do
case @client.strict_mode() do
true ->
Multi.new
|> Multi.run(:initial_version, fn %{} ->
version_id = get_sequence_id("versions") + 1
changeset_data = changeset.data |> Map.merge(%{
id: get_sequence_from_model(changeset) + 1,
first_version_id: version_id,
current_version_id: version_id
})
initial_version = make_version_struct(%{event: "insert"}, changeset_data, options)
@repo.insert(initial_version)
end)
|> Multi.run(:model, fn %{initial_version: initial_version} ->
updated_changeset = changeset |> change(%{
first_version_id: initial_version.id, current_version_id: initial_version.id
})
@repo.insert(updated_changeset)
end)
|> Multi.run(:version, fn %{initial_version: initial_version, model: model} ->
target_version = make_version_struct(%{event: "insert"}, model, options) |> serialize()
Version.changeset(initial_version, target_version) |> @repo.update
end)
|> @repo.transaction
_ ->
Multi.new
|> Multi.insert(:model, changeset)
|> Multi.run(:version, fn %{model: model} ->
version = make_version_struct(%{event: "insert"}, model, options)
@repo.insert(version)
transaction = Multi.new
|> Multi.run(:initial_version, fn %{} ->
version_id = get_sequence_id("versions") + 1
changeset_data = changeset.data |> Map.merge(%{
id: get_sequence_from_model(changeset) + 1,
first_version_id: version_id,
current_version_id: version_id
})
initial_version = make_version_struct(%{event: "insert"}, changeset_data, options)
@repo.insert(initial_version)
end)
|> @repo.transaction
|> Multi.run(:model, fn %{initial_version: initial_version} ->
updated_changeset = changeset |> change(%{
first_version_id: initial_version.id, current_version_id: initial_version.id
})
@repo.insert(updated_changeset)
end)
|> Multi.run(:version, fn %{initial_version: initial_version, model: model} ->
target_version = make_version_struct(%{event: "insert"}, model, options) |> serialize()
Version.changeset(initial_version, target_version) |> @repo.update
end)
|> @repo.transaction

case transaction do
{:ok, map} -> {:ok, Map.delete(map, :initial_version)}
{:error, transaction} -> {:error, transaction.model}
end
_ ->
transaction = Multi.new
|> Multi.insert(:model, changeset)
|> Multi.run(:version, fn %{model: model} ->
version = make_version_struct(%{event: "insert"}, model, options)
@repo.insert(version)
end)
|> @repo.transaction

case transaction do
{:error, :model, changeset, %{}} -> {:error, Map.merge(changeset, %{repo: @repo})}
_ -> transaction
end
end
end

Expand All @@ -89,40 +99,61 @@ defmodule PaperTrail do
def update(changeset, options \\ [sourced_by: nil, meta: nil]) do
case @client.strict_mode() do
true ->
Multi.new
|> Multi.run(:version, fn %{} ->
transaction = Multi.new
|> Multi.run(:initial_version, fn %{} ->
version_data = changeset.data |> Map.merge(%{current_version_id: get_sequence_id("versions")})
target_changeset = changeset |> Map.merge(%{data: version_data})
target_version = make_version_struct(%{event: "update"}, target_changeset, options)
@repo.insert(target_version)
end)
|> Multi.run(:model, fn %{version: version} ->
updated_changeset = changeset |> change(%{current_version_id: version.id})
|> Multi.run(:model, fn %{initial_version: initial_version} ->
updated_changeset = changeset |> change(%{current_version_id: initial_version.id})
@repo.update(updated_changeset)
end)
|> Multi.run(:version, fn %{initial_version: initial_version, model: model} ->
new_item_changes = initial_version.item_changes |> Map.merge(%{
current_version_id: initial_version.id
})
initial_version |> change(%{item_changes: new_item_changes}) |> @repo.update
end)
|> @repo.transaction

case transaction do
{:ok, map} -> {:ok, Map.delete(map, :initial_version)}
_ -> transaction
end
_ ->
Multi.new
transaction = Multi.new
|> Multi.update(:model, changeset)
|> Multi.run(:version, fn %{model: _model} ->
version = make_version_struct(%{event: "update"}, changeset, options)
@repo.insert(version)
end)
|> @repo.transaction

case transaction do
{:error, :model, changeset, %{}} -> {:error, Map.merge(changeset, %{repo: @repo})}
_ -> transaction
end
end
end

@doc """
Deletes a record from the database with a related version insertion in one transaction
"""
def delete(struct, options \\ [sourced_by: nil, meta: nil]) do
Multi.new
transaction = Multi.new
|> Multi.delete(:model, struct)
|> Multi.run(:version, fn %{} ->
version = make_version_struct(%{event: "delete"}, struct, options)
@repo.insert(version)
end)
|> @repo.transaction

case transaction do
{:error, :model, changeset, %{}} -> {:error, Map.merge(changeset, %{repo: @repo})}
_ -> transaction
end
end

defp make_version_struct(event_list, model, options \\ [])
Expand Down
12 changes: 8 additions & 4 deletions priv/repo/migrations/20160619190936_add_versions.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ defmodule Repo.Migrations.AddVersions do

def change do
create table(:versions) do
add :event, :string
add :item_type, :string
add :item_id, :integer
add :item_changes, :map
add :event, :string, null: false
add :item_type, :string, null: false
add :item_id, :integer, null: false
add :item_changes, :map, null: false
# add :owner_id # in future
add :sourced_by, :string, size: 50
add :meta, :map

add :inserted_at, :utc_datetime, null: false
end

create index(:versions, [:item_type, :item_id])
create index(:versions, [:event, :item_type])
create index(:versions, [:item_type, :inserted_at])
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Repo.Migrations.CreateSimpleCompanies do

def change do
create table(:simple_companies) do
add :name, :string
add :name, :string, null: false
add :is_active, :boolean
add :website, :string
add :city, :string
Expand Down
2 changes: 1 addition & 1 deletion priv/repo/migrations/20160619190938_add_simple_people.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Repo.Migrations.CreateSimplePeople do

def change do
create table(:simple_people) do
add :first_name, :string
add :first_name, :string, null: false
add :last_name, :string
add :visit_count, :integer
add :gender, :boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Repo.Migrations.CreateStrictCompanies do

def change do
create table(:strict_companies) do
add :name, :string
add :name, :string, null: false
add :is_active, :boolean
add :website, :string
add :city, :string
Expand Down
2 changes: 1 addition & 1 deletion priv/repo/migrations/20170319190940_add_strict_people.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Repo.Migrations.CreateStrictPeople do

def change do
create table(:strict_people) do
add :first_name, :string
add :first_name, :string, null: false
add :last_name, :string
add :visit_count, :integer
add :gender, :boolean
Expand Down
3 changes: 2 additions & 1 deletion test/helpers/simple_model_definitions.exs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ defmodule SimpleCompany do
def changeset(model, params \\ %{}) do
model
|> cast(params, @optional_fields)
|> cast_assoc(:people, required: false)
|> validate_required([:name])
|> no_assoc_constraint(:people)
end

def count do
Expand Down
1 change: 0 additions & 1 deletion test/helpers/strict_model_definitions.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ defmodule StrictCompany do
def changeset(model, params \\ %{}) do
model
|> cast(params, @optional_fields)
|> cast_assoc(:people, required: false)
end

def count do
Expand Down
36 changes: 28 additions & 8 deletions test/paper_trail_strict_mode_test.exs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# TODO: test error messages
defmodule PaperTrailStrictModeTest do
use ExUnit.Case

Expand Down Expand Up @@ -37,6 +38,7 @@ defmodule PaperTrailStrictModeTest do
company = result[:model] |> serialize()
version = result[:version] |> serialize()

assert Map.keys(result) == [:model, :version]
assert company_count == [1]
assert version_count == [1]
assert Map.drop(company, [:id, :inserted_at, :updated_at]) == %{
Expand All @@ -59,6 +61,7 @@ defmodule PaperTrailStrictModeTest do
sourced_by: nil,
meta: nil
}
assert company == first(Company, :id) |> @repo.one |> serialize
end

test "updating a company creates a company version with correct item_changes" do
Expand All @@ -71,6 +74,7 @@ defmodule PaperTrailStrictModeTest do
company = result[:model] |> serialize
version = result[:version] |> serialize

assert Map.keys(result) == [:model, :version]
assert company_count == [1]
assert version_count == [2]
assert Map.drop(company, [:id, :inserted_at, :updated_at]) == %{
Expand All @@ -85,20 +89,26 @@ defmodule PaperTrailStrictModeTest do
first_version_id: insert_company_result[:version].id,
current_version_id: version.id
}
# IMPORTANT: current_version also changes?
assert Map.drop(version, [:id, :inserted_at]) == %{
event: "update",
item_type: "StrictCompany",
item_id: company.id,
item_changes: %{city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc"},
item_changes: %{
city: "Hong Kong",
website: "http://www.acme.com",
facebook: "acme.llc",
current_version_id: version.id
},
sourced_by: nil,
meta: nil
}
assert company == first(Company, :id) |> @repo.one |> serialize
end

test "deleting a company creates a company version with correct attributes" do
{:ok, insert_company_result} = create_company_with_version()
{:ok, update_company_result} = update_company_with_version(insert_company_result[:model])
company_before_deletion = first(Company, :id) |> @repo.one |> serialize
{:ok, result} = PaperTrail.delete(update_company_result[:model])

company_count = Company.count()
Expand All @@ -107,6 +117,7 @@ defmodule PaperTrailStrictModeTest do
old_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(old_company, [:id, :inserted_at, :updated_at]) == %{
Expand Down Expand Up @@ -143,6 +154,7 @@ defmodule PaperTrailStrictModeTest do
sourced_by: nil,
meta: nil
}
assert old_company == company_before_deletion
end

test "creating a person with meta tag creates a person version with correct attributes" do
Expand All @@ -152,7 +164,7 @@ defmodule PaperTrailStrictModeTest do
is_active: true,
address: "Sesame street 100/3, 101010"
})
{:ok, insert_person_result} = Person.changeset(%Person{}, %{
{:ok, result} = Person.changeset(%Person{}, %{
first_name: "Izel",
last_name: "Nakri",
gender: true,
Expand All @@ -162,9 +174,10 @@ defmodule PaperTrailStrictModeTest do
person_count = Person.count()
version_count = Version.count()

person = insert_person_result[:model] |> serialize
version = insert_person_result[:version] |> serialize
person = result[:model] |> serialize
version = result[:version] |> serialize

assert Map.keys(result) == [:model, :version]
assert person_count == [1]
assert version_count == [3]
assert Map.drop(person, [:id, :inserted_at, :updated_at]) == %{
Expand All @@ -174,8 +187,8 @@ defmodule PaperTrailStrictModeTest do
visit_count: nil,
birthdate: nil,
company_id: insert_company_result[:model].id,
first_version_id: insert_person_result[:version].id,
current_version_id: insert_person_result[:version].id
first_version_id: result[:version].id,
current_version_id: result[:version].id
}
assert Map.drop(version, [:id, :inserted_at]) == %{
event: "insert",
Expand All @@ -185,6 +198,7 @@ defmodule PaperTrailStrictModeTest do
sourced_by: "admin",
meta: nil
}
assert person == first(Person, :id) |> @repo.one |> serialize
end

test "updating a person creates a person version with correct attributes" do
Expand All @@ -210,6 +224,7 @@ defmodule PaperTrailStrictModeTest do
person = result[:model] |> serialize
version = result[:version] |> serialize

assert Map.keys(result) == [:model, :version]
assert person_count == [1]
assert version_count == [4]
assert Map.drop(person, [:id, :inserted_at, :updated_at]) == %{
Expand All @@ -229,13 +244,15 @@ defmodule PaperTrailStrictModeTest do
item_changes: %{
first_name: "Isaac",
visit_count: 10,
birthdate: elem(Ecto.Date.cast(~D[1992-04-01]), 1)
birthdate: elem(Ecto.Date.cast(~D[1992-04-01]), 1),
current_version_id: version.id
},
sourced_by: "scraper",
meta: %{
linkname: "izelnakri"
}
}
assert person == first(Person, :id) |> @repo.one |> serialize
end

test "deleting a person creates a person version with correct attributes" do
Expand All @@ -254,6 +271,7 @@ defmodule PaperTrailStrictModeTest do
visit_count: 10,
birthdate: ~D[1992-04-01]
}) |> PaperTrail.update(sourced_by: "scraper", meta: %{linkname: "izelnakri"})
person_before_deletion = first(Person, :id) |> @repo.one |> serialize
{:ok, result} = PaperTrail.delete(update_person_result[:model])

person_count = Person.count()
Expand All @@ -262,6 +280,7 @@ defmodule PaperTrailStrictModeTest do
old_person = result[:model] |> serialize
version = result[:version] |> serialize

assert Map.keys(result) == [:model, :version]
assert person_count == [0]
assert version_count == [5]
assert Map.drop(version, [:id, :inserted_at]) == %{
Expand All @@ -284,6 +303,7 @@ defmodule PaperTrailStrictModeTest do
sourced_by: nil,
meta: nil
}
assert old_person == person_before_deletion
end

defp create_company_with_version(params \\ %{
Expand Down
Loading

0 comments on commit 711404d

Please sign in to comment.