Skip to content

Commit c5bbc36

Browse files
committed
Cleaned code
1 parent 0f8c54f commit c5bbc36

File tree

9 files changed

+71
-36
lines changed

9 files changed

+71
-36
lines changed

CHANGELOG

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@
22

33
- Made jsonpatch more Elixir-API-like by adding Jsonpatch.apply_patch! (which raise an exception) and changed Jsonpatch.apply_patch to return a tuple.
44
- Implemented escaping for '~' and '/'
5-
- Allow usage of '-' for Add operation
6-
- Fixed adding values to array
5+
- Allow usage of '-' for Add and Copy operation
6+
- Fixed adding and copying values to array
7+
- Improved error feedback of test operation
8+
- Fixed: Replace operation adds error to target
9+
- Cleaned code: Replaced strange constructs of Enum.with_index with Enum.fetch

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Features:
2020
- test
2121
3. De/Encoding and mapping
2222
4. Escaping of "`/`" (by "`~1`") and "`~`" (by "`~0`")
23-
5. Allow usage of `-` for appending things to list
23+
5. Allow usage of `-` for appending things to list (Add and Copy operation)
2424

2525

2626
## Getting started

lib/jsonpatch/operation/add.ex

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ defimpl Jsonpatch.Operation, for: Jsonpatch.Operation.Add do
3636
defp do_add({:error, _, _} = error, _target, _path, _value), do: error
3737

3838
# Map
39-
defp do_add({final_destination, last_fragment}, target, path, value)
40-
when is_map(final_destination) do
39+
defp do_add({%{} = final_destination, last_fragment}, target, path, value) do
4140
updated_final_destination = Map.put_new(final_destination, last_fragment, value)
4241
Jsonpatch.PathUtil.update_final_destination(target, updated_final_destination, path)
4342
end

lib/jsonpatch/operation/copy.ex

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,9 @@ defimpl Jsonpatch.Operation, for: Jsonpatch.Operation.Copy do
7070
{:error, :invalid_index, fragment}
7171

7272
{index, _} ->
73-
result =
74-
final_destination
75-
|> Enum.with_index()
76-
|> Enum.find(fn {_, other_index} -> index == other_index end)
77-
78-
case result do
79-
nil -> {:error, :invalid_index, fragment}
80-
{val, _} -> val
73+
case Enum.fetch(final_destination, index) do
74+
:error -> {:error, :invalid_index, fragment}
75+
{:ok, val} -> val
8176
end
8277
end
8378
end
@@ -88,12 +83,20 @@ defimpl Jsonpatch.Operation, for: Jsonpatch.Operation.Copy do
8883

8984
defp do_add({copy_target, _last_fragment}, copied_value, copy_path_end)
9085
when is_list(copy_target) do
91-
case Integer.parse(copy_path_end) do
92-
:error ->
93-
{:error, :invalid_index, copy_path_end}
94-
95-
{index, _} ->
96-
List.insert_at(copy_target, index, copied_value)
86+
if copy_path_end == "-" do
87+
List.insert_at(copy_target, length(copy_target), copied_value)
88+
else
89+
case Integer.parse(copy_path_end) do
90+
:error ->
91+
{:error, :invalid_index, copy_path_end}
92+
93+
{index, _} ->
94+
if index < length(copy_target) do
95+
List.update_at(copy_target, index, fn _old -> copied_value end)
96+
else
97+
{:error, :invalid_index, copy_path_end}
98+
end
99+
end
97100
end
98101
end
99102

lib/jsonpatch/path_util.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ defmodule Jsonpatch.PathUtil do
108108
defp find_final_destination(target, [fragment | tail]) when is_list(target) do
109109
{index, _} = Integer.parse(fragment)
110110

111-
case Enum.with_index(target) |> Enum.find(fn {_val, i} -> i == index end) do
112-
nil -> {:error, :invalid_index, fragment}
113-
{val, _} -> find_final_destination(val, tail)
111+
case Enum.fetch(target, index) do
112+
:error -> {:error, :invalid_index, fragment}
113+
{:ok, val} -> find_final_destination(val, tail)
114114
end
115115
end
116116

test/jsonpatch/operation/copy_test.exs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ defmodule Jsonpatch.Operation.CopyTest do
77
doctest Copy
88

99
test "Copy element by path with multiple indices" do
10-
path = "/a/b/1/c/3"
1110
from = "/a/b/1/c/2"
11+
# Copy to end
12+
path = "/a/b/1/c/-"
1213

1314
target = %{
1415
"a" => %{
@@ -114,4 +115,24 @@ defmodule Jsonpatch.Operation.CopyTest do
114115

115116
assert {:error, :invalid_index, "b"} = patched_target
116117
end
118+
119+
test "Copy list element" do
120+
patch = %Copy{from: "/a/0", path: "/a/1"}
121+
122+
target = %{"a" => [999, 888]}
123+
124+
patched = Operation.apply_op(patch, target)
125+
126+
assert %{"a" => [999, 999]} = patched
127+
end
128+
129+
test "Copy list element with invalid index" do
130+
patch = %Copy{from: "/a/0", path: "/a/5"}
131+
132+
target = %{"a" => [999, 888]}
133+
134+
patched_error = Operation.apply_op(patch, target)
135+
136+
assert {:error, :invalid_index, "5"} = patched_error
137+
end
117138
end
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
defmodule Jsonpatch.Operation.MoveTest do
22
use ExUnit.Case
33
doctest Jsonpatch.Operation.Move
4+
5+
# Move is a combination of the copy and remove operation.
46
end

test/jsonpatch/operation/remove_test.exs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule Jsonpatch.Operation.RemoveTest do
1+
defmodule RemoveTest do
22
use ExUnit.Case
33

44
alias Jsonpatch.Operation
@@ -53,7 +53,7 @@ defmodule Jsonpatch.Operation.RemoveTest do
5353
"home" => "Berlin"
5454
}
5555

56-
remove_patch = %Jsonpatch.Operation.Remove{path: "/nameX"}
56+
remove_patch = %Remove{path: "/nameX"}
5757
assert {:error, :invalid_path, "nameX"} = Jsonpatch.apply_patch(remove_patch, target)
5858
end
5959

@@ -65,7 +65,7 @@ defmodule Jsonpatch.Operation.RemoveTest do
6565
"home" => "Berlin"
6666
}
6767

68-
remove_patch = %Jsonpatch.Operation.Remove{path: "/hobbies/a"}
68+
remove_patch = %Remove{path: "/hobbies/a"}
6969
assert {:error, :invalid_index, "a"} = Jsonpatch.apply_patch(remove_patch, target)
7070

7171
# Longer path
@@ -76,18 +76,11 @@ defmodule Jsonpatch.Operation.RemoveTest do
7676
"home" => "Berlin"
7777
}
7878

79-
remove_patch = %Jsonpatch.Operation.Remove{path: "/hobbies/b/description"}
79+
remove_patch = %Remove{path: "/hobbies/b/description"}
8080
assert {:error, :invalid_index, "b"} = Jsonpatch.apply_patch(remove_patch, target)
8181

82-
# Longer path, numeric
83-
target = %{
84-
"name" => "Bob",
85-
"married" => false,
86-
"hobbies" => [%{"description" => "Foo"}],
87-
"home" => "Berlin"
88-
}
89-
90-
remove_patch = %Jsonpatch.Operation.Remove{path: "/hobbies/1/description"}
82+
# Longer path, numeric - out of
83+
remove_patch = %Remove{path: "/hobbies/1/description"}
9184
assert {:error, :invalid_index, "1"} = Jsonpatch.apply_patch(remove_patch, target)
9285
end
9386
end

test/jsonpatch/operation/test_test.exs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,18 @@ defmodule Jsonpatch.Operation.TestTest do
5151

5252
assert {:error, :test_failed, "Expected value '42' at '/a/b/1/c/1'"} = patched_target
5353
end
54+
55+
test "Test list with index out of range" do
56+
test = %Test{path: "/m/2", value: "foo"}
57+
target = %{"m" => [0, 1]}
58+
59+
assert {:error, :invalid_index, "2"} = Operation.apply_op(test, target)
60+
end
61+
62+
test "Test list with invalid index" do
63+
test = %Test{path: "/m/b", value: "foo"}
64+
target = %{"m" => [0, 1]}
65+
66+
assert {:error, :invalid_index, "b"} = Operation.apply_op(test, target)
67+
end
5468
end

0 commit comments

Comments
 (0)