Skip to content

Commit

Permalink
review
Browse files Browse the repository at this point in the history
  • Loading branch information
leftstanding committed Sep 30, 2023
1 parent a59c906 commit 08751b8
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on: push
env:
MIX_ENV: test
OTP_VERSION_SPEC: "24.2.1"
ELIXIR_VERSION_SPEC: "1.14"
ELIXIR_VERSION_SPEC: "1.13.3"

jobs:
compile:
Expand Down
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
elixir 1.14.2-otp-25
erlang 25.1.2
elixir 1.13.3-otp-24
erlang 24.2.1
37 changes: 25 additions & 12 deletions lib/ecto_diff.ex
Original file line number Diff line number Diff line change
Expand Up @@ -367,33 +367,45 @@ defmodule EctoDiff do
end
end

defp diff_association(previous, current, %{cardinality: :many, through: [through, field]}, acc, opts) do
defp diff_association(
previous,
current,
%{cardinality: :many, through: [through, assoc_field], owner: owner},
acc,
opts
) do
assoc_diff =
acc
|> Keyword.get_values(through)
|> List.flatten()
|> Enum.map(& &1[:changes][field])
|> Enum.map(& &1[:changes][assoc_field])

diff =
case assoc_diff do
[_ | _] = diff ->
List.flatten(diff)

_ ->
{previous, current} =
case length(previous) - length(current) do
0 -> {previous, current}
n when n > 0 -> {previous, current ++ List.duplicate(nil, n)}
n when n < 0 -> {previous ++ List.duplicate(nil, -n), current}
end

Enum.zip_with([previous, current], fn [p, c] -> do_diff(p, c, opts) end)
through_association = owner.__schema__(:association, through).related
association = through_association.__schema__(:association, assoc_field)

diff_association(previous, current, association, acc, opts)
|> Keyword.get_values(assoc_field)
|> List.flatten()
end

if no_changes?(diff), do: acc, else: [{field, diff} | acc]
if no_changes?(diff), do: acc, else: [{assoc_field, diff} | acc]
end

defp diff_association(previous, current, %{cardinality: :many, field: field, related: struct}, acc, opts) do
defp diff_association(
previous,
current,
%{cardinality: :many, field: field} = association,
acc,
opts
) do
%{related: struct} = association

primary_key_fields = get_primary_key_fields(struct, opts)

if primary_key_fields == [],
Expand Down Expand Up @@ -455,6 +467,7 @@ defmodule EctoDiff do
end

defp no_changes?([_ | _] = changes), do: Enum.any?(changes, &no_changes?/1)
defp no_changes?([]), do: true
defp no_changes?(%{effect: effect, changes: map}) when map == %{} and effect in [:added, :changed], do: true
defp no_changes?(_), do: false

Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule EctoDiff.MixProject do
[
app: :ecto_diff,
version: @version,
elixir: "~> 1.14",
elixir: "~> 1.7",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
deps: deps(),
Expand Down
15 changes: 9 additions & 6 deletions test/ecto_diff_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -733,13 +733,16 @@ defmodule EctoDiffTest do
})
|> Repo.update()

updated_pet = Repo.preload(updated_pet, [:resources, :toys])
updated_pet = Repo.preload(updated_pet, :toys)

id = pet.id
[%{id: resource_id}] = updated_pet.resources
[ball_id, mouse_id] = Enum.map(updated_pet.toys, & &1.id)
%{"ball" => ball_id, "mouse" => mouse_id} = Enum.into(updated_pet.toys, %{}, &{&1.name, &1.id})

{:ok, diff} = EctoDiff.diff(pet, updated_pet)
[%{changes: %{toys: resource_toys}}] = diff.changes.resources

assert resource_toys == diff.changes.toys

assert %EctoDiff{
effect: :changed,
Expand Down Expand Up @@ -799,9 +802,9 @@ defmodule EctoDiffTest do
|> Repo.insert()

id = pet.id
pet = Repo.preload(pet, [:resources, :toys])
pet = Repo.preload(pet, :toys)

[ball_id, mouse_id] = Enum.map(pet.toys, & &1.id)
%{"ball" => ball_id, "mouse" => mouse_id} = Enum.into(pet.toys, %{}, &{&1.name, &1.id})
[%{id: resource_id}] = pet.resources

{:ok, updated_pet} =
Expand Down Expand Up @@ -855,7 +858,7 @@ defmodule EctoDiffTest do
|> Pet.new()
|> Repo.insert()

pet = Repo.preload(pet, [:resources, :toys])
pet = Repo.preload(pet, :toys)
id = pet.id
[%{id: resource_id}] = pet.resources
[ball_id] = Enum.map(pet.toys, & &1.id)
Expand Down Expand Up @@ -902,7 +905,7 @@ defmodule EctoDiffTest do
|> Pet.new()
|> Repo.insert()

pet = Repo.preload(pet, [:resources, :toys])
pet = Repo.preload(pet, :toys)
{:ok, updated_pet} = pet |> Pet.update(%{name: "McFluffFace"}) |> Repo.update()
id = pet.id

Expand Down

0 comments on commit 08751b8

Please sign in to comment.