Current section

Files

Jump to
paper_trail lib paper_trail.ex
Raw

lib/paper_trail.ex

defmodule PaperTrail do
alias Ecto.Multi
import Ecto.Query
alias Model.Version
@doc """
Gets all the versions of a record given a module and its id
"""
def get_versions(model, id) do
item_type = model |> Module.split |> List.last
version_query(item_type, id) |> Application.Repo.all
end
@doc """
Gets all the versions of a record
"""
def get_versions(record) do
item_type = record.__struct__ |> Module.split |> List.last
version_query(item_type, record.id) |> Application.Repo.all
end
@doc """
Gets the last version of a record given its module reference and its id
"""
def get_version(model, id) do
item_type = Module.split(model) |> List.last
last(version_query(item_type, id)) |> Application.Repo.one
end
@doc """
Gets the last version of a record
"""
def get_version(record) do
item_type = record.__struct__ |> Module.split |> List.last
last(version_query(item_type, record.id)) |> Application.Repo.one
end
defp version_query(item_type, id) do
from v in Version,
where: v.item_type == ^item_type and v.item_id == ^id
end
# changeset = Model.changeset(Ecto.Repo.get(Model, id), params)
@doc """
Inserts a record to the database with a related version insertion in one transaction
"""
def insert(struct, meta \\ nil) do
Multi.new
|> Multi.insert(:model, struct)
|> Multi.run(:version, fn %{model: model} ->
version = make_version_struct(%{event: "create"}, model, meta)
Application.Repo.insert(version)
end)
|> Application.Repo.transaction
end
# might make the changeset version
@doc """
Updates a record from the database with a related version insertion in one transaction
"""
def update(changeset, meta \\ nil) do
Multi.new
|> Multi.update(:model, changeset)
|> Multi.run(:version, fn %{model: model} ->
version = make_version_struct(%{event: "update"}, changeset, meta)
Application.Repo.insert(version)
end)
|> Application.Repo.transaction
end
@doc """
Deletes a record from the database with a related version insertion in one transaction
"""
def delete(struct, meta \\ nil) do
Multi.new
|> Multi.delete(:model, struct)
|> Multi.run(:version, fn %{model: model} ->
version = make_version_struct(%{event: "destroy"}, model, meta)
Application.Repo.insert(version)
end)
|> Application.Repo.transaction
end
defp make_version_struct(%{event: "create"}, model, meta) do
%Version{
event: "create",
item_type: model.__struct__ |> Module.split |> List.last,
item_id: model.id,
item_changes: Map.drop(model, [:__struct__, :__meta__]),
meta: meta
}
end
defp make_version_struct(%{event: "update"}, changeset, meta) do
%Version{
event: "update",
item_type: changeset.data.__struct__ |> Module.split |> List.last,
item_id: changeset.data.id,
item_changes: changeset.changes,
meta: meta
}
end
defp make_version_struct(%{event: "destroy"}, model, meta) do
%Version{
event: "destroy",
item_type: model.__struct__ |> Module.split |> List.last,
item_id: model.id,
item_changes: Map.drop(model, [:__struct__, :__meta__]),
meta: meta
}
end
end