@@ -57,23 +57,60 @@ if Code.ensure_loaded?(Ecto) do
57
57
resolve ( repo , query , args )
58
58
end
59
59
60
+ @ doc """
61
+ Pass in an Ecto.Repo, an Ecto.Query, and Relay args to have the query
62
+ executed and results returned in the format Relay requires.
63
+
64
+ If you wish to have the results ordered by some field other than `id`,
65
+ use `ordered_by` and `ordered_by_direction`.
66
+
67
+ Example for returning data in reverse chronological order (newest first)
68
+ like you would do for a page listing blog posts:
69
+
70
+ args = %{
71
+ first: 10,
72
+ ordered_by: :inserted_at,
73
+ ordered_by_direction: :desc
74
+ }
75
+
76
+ Your GraphQL resolve function for the connection will look something like:
77
+
78
+ resolve: fn(blog, args, _ctx) ->
79
+ # Order by desc inserted_at
80
+ args = Map.merge(args, %{ordered_by: :inserted_at, ordered_by_direction: :desc})
81
+ query = Ecto.assoc(blog, :posts)
82
+ GraphQL.Relay.Connection.Ecto.resolve(Repo, query, args)
83
+ end
84
+ """
60
85
def resolve ( repo , query , args \\ % { } ) do
61
86
before = cursor_to_offset ( args [ :before ] )
62
87
# `after` is a keyword http://elixir-lang.org/docs/master/elixir/Kernel.SpecialForms.html#try/1
63
88
a_after = cursor_to_offset ( args [ :after ] )
64
89
first = args [ :first ]
65
90
last = args [ :last ]
66
91
ordered_by_property = args [ :ordered_by ] || :id
92
+ ordered_by_direction = get_ordered_by_direction ( args [ :ordered_by_direction ] || :asc )
93
+ opposite_ordered_by_direction = if ordered_by_direction == :asc , do: :desc , else: :asc
67
94
limit = Enum . min ( [ first , last , connection_count ( repo , query ) ] )
68
95
69
96
query = if a_after do
70
- query |> where ( [ a ] , field ( a , ^ ordered_by_property ) > ^ a_after )
97
+ case ordered_by_direction do
98
+ :asc ->
99
+ query |> where ( [ a ] , field ( a , ^ ordered_by_property ) > ^ a_after )
100
+ :desc ->
101
+ query |> where ( [ a ] , field ( a , ^ ordered_by_property ) < ^ a_after )
102
+ end
71
103
else
72
104
query
73
105
end
74
106
75
107
query = if before do
76
- query |> where ( [ a ] , field ( a , ^ ordered_by_property ) < ^ before )
108
+ case ordered_by_direction do
109
+ :asc ->
110
+ query |> where ( [ a ] , field ( a , ^ ordered_by_property ) < ^ before )
111
+ :desc ->
112
+ query |> where ( [ a ] , field ( a , ^ ordered_by_property ) > ^ before )
113
+ end
77
114
else
78
115
query
79
116
end
@@ -98,13 +135,15 @@ if Code.ensure_loaded?(Ecto) do
98
135
end
99
136
100
137
query = if first do
101
- query |> order_by ( asc: ^ ordered_by_property ) |> limit ( ^ limit )
138
+ sort_values = Keyword . new ( [ { ordered_by_direction , ordered_by_property } ] )
139
+ query |> order_by ( ^ sort_values ) |> limit ( ^ limit )
102
140
else
103
141
query
104
142
end
105
143
106
144
query = if last do
107
- query |> order_by ( desc: ^ ordered_by_property ) |> limit ( ^ limit )
145
+ sort_values = Keyword . new ( [ { opposite_ordered_by_direction , ordered_by_property } ] )
146
+ query |> order_by ( ^ sort_values ) |> limit ( ^ limit )
108
147
else
109
148
query
110
149
end
@@ -166,6 +205,10 @@ if Code.ensure_loaded?(Ecto) do
166
205
repo . one ( count_query )
167
206
end
168
207
208
+ defp get_ordered_by_direction ( value ) when value in [ :asc , :desc ] do
209
+ value
210
+ end
211
+
169
212
defp make_query_countable ( query ) do
170
213
query
171
214
|> remove_order
0 commit comments