Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Commit 19e24b0

Browse files
committed
Move the expansion code into ArrayMap
1 parent 4d4cc5e commit 19e24b0

File tree

3 files changed

+39
-21
lines changed

3 files changed

+39
-21
lines changed

lib/graphql/execution/executor.ex

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,33 +46,17 @@ defmodule GraphQL.Execution.Executor do
4646
case operation.operation do
4747
:query ->
4848
{context, result} = execute_fields(context, type, root_value, fields)
49-
{:ok, expand_array_maps(result), context.errors}
49+
{:ok, ArrayMap.expand_result(result), context.errors}
5050
:mutation ->
5151
{context, result} = execute_fields_serially(context, type, root_value, fields)
52-
{:ok, expand_array_maps(result), context.errors}
52+
{:ok, ArrayMap.expand_result(result), context.errors}
5353
:subscription ->
5454
{:error, "Subscriptions not currently supported"}
5555
_ ->
5656
{:error, "Can only execute queries, mutations and subscriptions"}
5757
end
5858
end
5959

60-
defp expand_array_maps(result) when is_list(result) do
61-
Enum.map(result, &expand_array_maps/1)
62-
end
63-
defp expand_array_maps(%ArrayMap{} = result) do
64-
Enum.reduce(Enum.sort(Map.keys(result.map)), [], fn(index, acc) ->
65-
[expand_array_maps(Map.get(result.map, index))] ++ acc
66-
end) |> Enum.reverse
67-
end
68-
defp expand_array_maps(result) when is_map(result) do
69-
Enum.reduce(result, %{}, fn({k, v}, acc) ->
70-
Map.put(acc, expand_array_maps(k), expand_array_maps(v))
71-
end)
72-
end
73-
defp expand_array_maps(result), do: result
74-
75-
7660
defp collect_selections(context, runtime_type, selection_set, field_fragment_map \\ %{fields: %{}, fragments: %{}}) do
7761
Enum.reduce selection_set[:selections], {context, field_fragment_map}, fn(selection, {context, field_fragment_map}) ->
7862
collect_selection(context, runtime_type, selection, field_fragment_map)

lib/graphql/util/array_map.ex

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ defmodule GraphQL.Util.ArrayMap do
1010

1111
defstruct map: %{}
1212

13+
def new(map) do
14+
if !Enum.all?(Map.keys(map), fn(key) -> is_integer(key) end) do
15+
raise "all key must be integers!"
16+
end
17+
%__MODULE__{map: map}
18+
end
19+
1320
def put(array_map, index, value) when is_integer(index) do
1421
%__MODULE__{ map: Map.put(array_map.map, index, value) }
1522
end
@@ -29,11 +36,29 @@ defmodule GraphQL.Util.ArrayMap do
2936

3037
def get(array_map, key, value) do
3138
map = Access.get(array_map.map, key, value)
32-
%__MODULE__{map: value}
39+
%__MODULE__{map: map}
3340
end
3441

3542
def pop(array_map, key) do
3643
{value, map} = Access.get(array_map.map, key)
3744
{value, %__MODULE__{map: map}}
3845
end
46+
47+
# Converts an intermediate executor result that contains ArrayMaps into one
48+
# where the array maps are converted into lists.
49+
def expand_result(result) when is_list(result) do
50+
Enum.map(result, &expand_result/1)
51+
end
52+
def expand_result(%__MODULE__{} = result) do
53+
Enum.reduce(Enum.sort(Map.keys(result.map)), [], fn(index, acc) ->
54+
[expand_result(Map.get(result.map, index))] ++ acc
55+
end) |> Enum.reverse
56+
end
57+
def expand_result(result) when is_map(result) do
58+
Enum.reduce(result, %{}, fn({k, v}, acc) ->
59+
Map.put(acc, expand_result(k), expand_result(v))
60+
end)
61+
end
62+
def expand_result(result), do: result
63+
3964
end

test/graphql/util/array_map_test.exs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@ defmodule GraphQL.Util.ArrayMapTest do
55
alias GraphQL.Util.ArrayMap
66

77
test "implements Access" do
8-
version_1 = %ArrayMap{map: %{0 => :zero, 1 => :one, 2 => :two}}
9-
version_2 = %ArrayMap{map: %{0 => :zero, 1 => :ONE, 2 => :two}}
8+
version_1 = ArrayMap.new(%{0 => :zero, 1 => :one, 2 => :two})
9+
version_2 = ArrayMap.new(%{0 => :zero, 1 => :ONE, 2 => :two})
1010

1111
version_1_updated = put_in(version_1, [1], :ONE)
1212

1313
assert version_2 == version_1_updated
1414
end
15+
16+
test "Access works with mix of nested Maps and ArrayMaps" do
17+
nested = %{:foo => ArrayMap.new(%{0 => %{:baz => ArrayMap.new(%{0 => %{quux: 123}})}})}
18+
expected = %{:foo => ArrayMap.new(%{0 => %{:baz => ArrayMap.new(%{0 => %{quux: 456}})}})}
19+
20+
updated = put_in(nested, [:foo, 0, :baz, 0, :quux], 456)
21+
22+
assert updated == expected
23+
end
1524
end

0 commit comments

Comments
 (0)