Skip to content

Commit 1d1cc4b

Browse files
authored
Merge pull request #1052 from cerebris/pr/1041
Pr/1041
2 parents e58687c + 3c0fb13 commit 1d1cc4b

File tree

2 files changed

+50
-42
lines changed

2 files changed

+50
-42
lines changed

lib/jsonapi/active_record_accessor.rb

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -211,28 +211,33 @@ def apply_pagination(records, paginator, order_options)
211211

212212
def apply_sort(records, order_options, context = {})
213213
if defined?(_resource_klass.apply_sort)
214-
_resource_klass.apply_sort(records, order_options, context)
214+
custom_sort = _resource_klass.apply_sort(records, order_options, context)
215+
custom_sort.nil? ? default_sort(records, order_options) : custom_sort
215216
else
216-
if order_options.any?
217-
order_options.each_pair do |field, direction|
218-
if field.to_s.include?(".")
219-
*model_names, column_name = field.split(".")
220-
221-
associations = _lookup_association_chain([records.model.to_s, *model_names])
222-
joins_query = _build_joins([records.model, *associations])
223-
224-
# _sorting is appended to avoid name clashes with manual joins eg. overridden filters
225-
order_by_query = "#{associations.last.name}_sorting.#{column_name} #{direction}"
226-
records = records.joins(joins_query).order(order_by_query)
227-
else
228-
field = _resource_klass._attribute_delegated_name(field)
229-
records = records.order(field => direction)
230-
end
217+
default_sort(records, order_options)
218+
end
219+
end
220+
221+
def default_sort(records, order_options)
222+
if order_options.any?
223+
order_options.each_pair do |field, direction|
224+
if field.to_s.include?(".")
225+
*model_names, column_name = field.split(".")
226+
227+
associations = _lookup_association_chain([records.model.to_s, *model_names])
228+
joins_query = _build_joins([records.model, *associations])
229+
230+
# _sorting is appended to avoid name clashes with manual joins eg. overridden filters
231+
order_by_query = "#{associations.last.name}_sorting.#{column_name} #{direction}"
232+
records = records.joins(joins_query).order(order_by_query)
233+
else
234+
field = _resource_klass._attribute_delegated_name(field)
235+
records = records.order(field => direction)
231236
end
232237
end
233-
234-
records
235238
end
239+
240+
records
236241
end
237242

238243
def _lookup_association_chain(model_names)
@@ -474,7 +479,7 @@ def preload_included_fragments(src_res_class, resource_pile, path, serializer, o
474479
next unless src_res
475480
fragment = target_resources[tgt_id]
476481
next unless fragment
477-
src_res.preloaded_fragments[serialized_rel_name][tgt_id] = fragment
482+
src_res.preloaded_fragments[serialized_rel_name][tgt_id] = fragment
478483
end
479484
end
480485

test/unit/resource/resource_test.rb

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -391,12 +391,36 @@ def apply_filters(records, filters, options)
391391
end
392392
end
393393

394+
def test_custom_sorting
395+
post_resource = PostResource.new(Post.find(1), nil)
396+
comment_ids = post_resource.comments.map{|c| c._model.id }
397+
assert_equal [1,2], comment_ids
398+
399+
# define apply_sort method on post resource that will never sort
400+
PostResource.instance_eval do
401+
def apply_sort(records, criteria, context = {})
402+
if criteria.key?('name')
403+
# this sort will never occure
404+
records.order('name asc')
405+
end
406+
end
407+
end
408+
409+
sorted_comment_ids = post_resource.comments(sort_criteria: [{ field: 'id', direction: :desc}]).map{|c| c._model.id }
410+
assert_equal [2,1], sorted_comment_ids
411+
ensure
412+
# reset method to original implementation
413+
PostResource.instance_eval do
414+
undef :apply_sort
415+
end
416+
end
417+
394418
def test_to_many_relationship_sorts
395419
post_resource = PostResource.new(Post.find(1), nil)
396420
comment_ids = post_resource.comments.map{|c| c._model.id }
397421
assert_equal [1,2], comment_ids
398422

399-
# define apply_filters method on post resource to sort descending
423+
# define apply_sort method on post resource to sort descending
400424
PostResource.instance_eval do
401425
def apply_sort(records, criteria, context = {})
402426
# :nocov:
@@ -412,28 +436,7 @@ def apply_sort(records, criteria, context = {})
412436
ensure
413437
# reset method to original implementation
414438
PostResource.instance_eval do
415-
def apply_sort(records, order_options, _context = {})
416-
# :nocov:
417-
if order_options.any?
418-
order_options.each_pair do |field, direction|
419-
if field.to_s.include?(".")
420-
*model_names, column_name = field.split(".")
421-
422-
associations = _lookup_association_chain([records.model.to_s, *model_names])
423-
joins_query = _record_accessor._build_joins([records.model, *associations])
424-
425-
# _sorting is appended to avoid name clashes with manual joins eg. overriden filters
426-
order_by_query = "#{associations.last.name}_sorting.#{column_name} #{direction}"
427-
records = records.joins(joins_query).order(order_by_query)
428-
else
429-
records = records.order(field => direction)
430-
end
431-
end
432-
end
433-
434-
records
435-
# :nocov:
436-
end
439+
undef :apply_sort
437440
end
438441
end
439442

0 commit comments

Comments
 (0)