Skip to content

Commit b1abcc1

Browse files
authored
Merge pull request #3 from valiot/gdavila/TEAPP-23-delete-and-log
delete and log function
2 parents 3b70013 + bade652 commit b1abcc1

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

lib/ecto_trail/changelog.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ defmodule EctoTrail.Changelog do
1010
field(:resource_id, :string)
1111
field(:changeset, :map)
1212

13-
timestamps([type: :utc_datetime, updated_at: false])
13+
timestamps(type: :utc_datetime, updated_at: false)
1414
end
1515
end

lib/ecto_trail/ecto_trail.ex

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ defmodule EctoTrail do
7878
| {:error, Ecto.Changeset.t()}
7979
def update_and_log(changeset, actor_id, opts \\ []),
8080
do: EctoTrail.update_and_log(__MODULE__, changeset, actor_id, opts)
81+
82+
@doc """
83+
Call `c:Ecto.Repo.delete/2` operation and store deleted objext in a `change_log` table.
84+
"""
85+
@spec delete_and_log(
86+
struct_or_changeset :: Ecto.Schema.t() | Ecto.Changeset.t(),
87+
actor_id :: String.T,
88+
opts :: Keyword.t()
89+
) ::
90+
{:ok, Ecto.Schema.t()}
91+
| {:error, Ecto.Changeset.t()}
92+
def delete_and_log(struct_or_changeset, actor_id, opts \\ []),
93+
do: EctoTrail.delete_and_log(__MODULE__, struct_or_changeset, actor_id, opts)
8194
end
8295
end
8396

@@ -95,7 +108,7 @@ defmodule EctoTrail do
95108
def insert_and_log(repo, struct_or_changeset, actor_id, opts \\ []) do
96109
Multi.new()
97110
|> Multi.insert(:operation, struct_or_changeset, opts)
98-
|> run_logging_transaction(repo, struct_or_changeset, actor_id)
111+
|> run_logging_transaction(repo, struct_or_changeset, actor_id, 1)
99112
end
100113

101114
@doc """
@@ -114,12 +127,29 @@ defmodule EctoTrail do
114127
def update_and_log(repo, changeset, actor_id, opts \\ []) do
115128
Multi.new()
116129
|> Multi.update(:operation, changeset, opts)
117-
|> run_logging_transaction(repo, changeset, actor_id)
130+
|> run_logging_transaction(repo, changeset, actor_id, 2)
118131
end
119132

120-
defp run_logging_transaction(multi, repo, struct_or_changeset, actor_id) do
133+
@doc """
134+
Call `c:Ecto.Repo.delete/2` operation and store deleted objext in a `change_log` table.
135+
"""
136+
@spec delete_and_log(
137+
repo :: Ecto.Repo.t(),
138+
struct_or_changeset :: Ecto.Schema.t() | Ecto.Changeset.t(),
139+
actor_id :: String.T,
140+
opts :: Keyword.t()
141+
) ::
142+
{:ok, Ecto.Schema.t()}
143+
| {:error, Ecto.Changeset.t()}
144+
def delete_and_log(repo, struct_or_changeset, actor_id, opts \\ []) do
145+
Multi.new()
146+
|> Multi.delete(:operation, struct_or_changeset, opts)
147+
|> run_logging_transaction(repo, struct_or_changeset, actor_id, 3)
148+
end
149+
150+
defp run_logging_transaction(multi, repo, struct_or_changeset, actor_id, operation_type) do
121151
multi
122-
|> Multi.run(:changelog, &log_changes(repo, &1, struct_or_changeset, actor_id))
152+
|> Multi.run(:changelog, &log_changes(repo, &1, struct_or_changeset, actor_id, operation_type))
123153
|> repo.transaction()
124154
|> build_result()
125155
end
@@ -130,7 +160,7 @@ defmodule EctoTrail do
130160
defp build_result({:error, :operation, reason, _changes_so_far}),
131161
do: {:error, reason}
132162

133-
defp log_changes(repo, multi_acc, struct_or_changeset, actor_id) do
163+
defp log_changes(repo, multi_acc, struct_or_changeset, actor_id, operation_type) do
134164
%{operation: operation} = multi_acc
135165
associations = operation.__struct__.__schema__(:associations)
136166
resource = operation.__struct__.__schema__(:source)
@@ -141,6 +171,7 @@ defmodule EctoTrail do
141171
|> get_changes()
142172
|> get_embed_changes(embeds)
143173
|> get_assoc_changes(associations)
174+
|> validate_changes(struct_or_changeset, operation_type)
144175

145176
result =
146177
%{
@@ -166,6 +197,40 @@ defmodule EctoTrail do
166197
end
167198
end
168199

200+
defp validate_changes(changes, schema, operation_type) do
201+
case operation_type do
202+
1 ->
203+
# this case is entered when the operation type it's an insert operation
204+
changes
205+
206+
2 ->
207+
# this case is entered when the operation type it's an update operation
208+
changes
209+
210+
3 ->
211+
# this case is entered when the operation type it's a delete operation
212+
{_, regreso} =
213+
Map.from_struct(schema)
214+
|> Map.pop(:__meta__)
215+
216+
IO.inspect(regreso)
217+
remove_empty_assosiations(regreso)
218+
end
219+
end
220+
221+
defp remove_empty_assosiations(struct) do
222+
new_struct =
223+
Enum.map(struct, fn {key, value} ->
224+
{key,
225+
if String.contains?(Kernel.inspect(value), "Ecto.Association.NotLoaded") do
226+
nil
227+
else
228+
value
229+
end}
230+
end)
231+
|> Map.new()
232+
end
233+
169234
defp get_changes(%Changeset{changes: changes}),
170235
do: map_custom_ecto_types(changes)
171236

0 commit comments

Comments
 (0)