@@ -70,6 +70,10 @@ defmodule Ash.Test.Sort.SortTest do
7070 calculate :title_calculation , :string , expr ( title ) ,
7171 public?: true ,
7272 sortable?: false
73+
74+ calculate :context_dependent , :string , Ash.Test.Sort.SortTest.ContextDependent do
75+ public? true
76+ end
7377 end
7478
7579 relationships do
@@ -124,6 +128,19 @@ defmodule Ash.Test.Sort.SortTest do
124128 end
125129 end
126130
131+ defmodule ContextDependent do
132+ @ moduledoc false
133+ use Ash.Resource.Calculation
134+
135+ @ impl true
136+ def expression ( _opts , context ) do
137+ case context . source_context [ :sort_field ] do
138+ nil -> raise "requires :sort_field in the source context"
139+ field -> expr ( ^ ref ( field ) )
140+ end
141+ end
142+ end
143+
127144 defmodule NoSortDataLayer do
128145 use Spark.Dsl.Extension , sections: [ ]
129146
@@ -189,6 +206,33 @@ defmodule Ash.Test.Sort.SortTest do
189206 end
190207 end
191208
209+ describe "sorting on calculations whose expression/2 reads context.source_context" do
210+ test "does not raise when the query has no context set" do
211+ assert % Ash.Query { valid?: true } = Ash.Query . sort ( Post , context_dependent: :asc )
212+ end
213+
214+ test "does not raise when the query context was set before sorting" do
215+ assert % Ash.Query { valid?: true } =
216+ Post
217+ |> Ash.Query . set_context ( % { sort_field: :title } )
218+ |> Ash.Query . sort ( context_dependent: :asc )
219+ end
220+
221+ test "reads successfully when the context is set" do
222+ b = Post |> Ash.Changeset . for_create ( :create , % { title: "b" } ) |> Ash . create! ( )
223+ a = Post |> Ash.Changeset . for_create ( :create , % { title: "a" } ) |> Ash . create! ( )
224+
225+ ids =
226+ Post
227+ |> Ash.Query . set_context ( % { sort_field: :title } )
228+ |> Ash.Query . sort ( context_dependent: :asc )
229+ |> Ash . read! ( )
230+ |> Enum . map ( & & 1 . id )
231+
232+ assert ids == [ a . id , b . id ]
233+ end
234+ end
235+
192236 describe "parse_input/2" do
193237 test "simple string sort parses properly" do
194238 assert { :ok , [ title: :asc , contents: :desc ] } =
@@ -333,38 +377,47 @@ defmodule Ash.Test.Sort.SortTest do
333377 end
334378 end
335379
336- test "expression sorts reject references to unsortable fields and relationships" do
380+ test "expression sorts reject references to unsortable fields and relationships at read time " do
337381 require Ash.Sort
338382
339- assert % Ash.Query {
340- valid?: false ,
341- errors: [
342- % Ash.Error.Query.UnsortableField {
343- resource: Ash.Test.Sort.SortTest.Post ,
344- field: :unsortable_title
345- }
346- ]
347- } = Ash.Query . sort ( Post , Ash.Sort . expr_sort ( unsortable_title , :string ) )
348-
349- assert % Ash.Query {
350- valid?: false ,
351- errors: [
352- % Ash.Error.Query.UnsortableField {
353- resource: Ash.Test.Sort.SortTest.Author ,
354- field: :unsortable_name
355- }
356- ]
357- } = Ash.Query . sort ( Post , Ash.Sort . expr_sort ( author . unsortable_name , :string ) )
358-
359- assert % Ash.Query {
360- valid?: false ,
361- errors: [
362- % Ash.Error.Query.UnsortableField {
363- resource: Ash.Test.Sort.SortTest.Post ,
364- field: :unsortable_author
365- }
366- ]
367- } = Ash.Query . sort ( Post , Ash.Sort . expr_sort ( unsortable_author . name , :string ) )
383+ assert { :error ,
384+ % Ash.Error.Invalid {
385+ errors: [
386+ % Ash.Error.Query.UnsortableField {
387+ resource: Ash.Test.Sort.SortTest.Post ,
388+ field: :unsortable_title
389+ }
390+ ]
391+ } } =
392+ Post
393+ |> Ash.Query . sort ( Ash.Sort . expr_sort ( unsortable_title , :string ) )
394+ |> Ash . read ( )
395+
396+ assert { :error ,
397+ % Ash.Error.Invalid {
398+ errors: [
399+ % Ash.Error.Query.UnsortableField {
400+ resource: Ash.Test.Sort.SortTest.Author ,
401+ field: :unsortable_name
402+ }
403+ ]
404+ } } =
405+ Post
406+ |> Ash.Query . sort ( Ash.Sort . expr_sort ( author . unsortable_name , :string ) )
407+ |> Ash . read ( )
408+
409+ assert { :error ,
410+ % Ash.Error.Invalid {
411+ errors: [
412+ % Ash.Error.Query.UnsortableField {
413+ resource: Ash.Test.Sort.SortTest.Post ,
414+ field: :unsortable_author
415+ }
416+ ]
417+ } } =
418+ Post
419+ |> Ash.Query . sort ( Ash.Sort . expr_sort ( unsortable_author . name , :string ) )
420+ |> Ash . read ( )
368421 end
369422
370423 test "nested sorts enforce field and relationship flags" do
0 commit comments