Skip to content

Commit 5139d84

Browse files
authored
Merge pull request #938 from cerebris/fix_933_master
Fix 933 - Sort with has one include
2 parents 357278f + 022bd5c commit 5139d84

4 files changed

Lines changed: 48 additions & 14 deletions

File tree

lib/jsonapi/resource.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,6 @@ def preload_included_fragments(resources, records, serializer, options)
11021102
include_directives = options[:include_directives]
11031103
return unless include_directives
11041104

1105-
relevant_options = options.except(:include_directives, :order, :paginator)
11061105
context = options[:context]
11071106

11081107
# For each association, including indirect associations, find the target record ids.
@@ -1196,7 +1195,7 @@ def preload_included_fragments(resources, records, serializer, options)
11961195
.map(&:last)
11971196
.reject{|id| target_resources[klass.name].has_key?(id) }
11981197
.uniq
1199-
found = klass.find({klass._primary_key => sub_res_ids}, relevant_options)
1198+
found = klass.find({klass._primary_key => sub_res_ids}, context: options[:context])
12001199
target_resources[klass.name].merge! found.map{|r| [r.id, r] }.to_h
12011200
end
12021201

lib/jsonapi/resource_serializer.rb

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,35 @@ def serialize_to_hash(source)
5050

5151
@included_objects = {}
5252

53-
process_primary(source, @include_directives.include_directives)
53+
process_source_objects(source, @include_directives.include_directives)
5454

55-
included_objects = []
5655
primary_objects = []
56+
57+
# pull the processed objects corresponding to the source objects. Ensures we preserve order.
58+
if is_resource_collection
59+
source.each do |primary|
60+
if primary.id
61+
case primary
62+
when CachedResourceFragment then primary_objects.push(@included_objects[primary.type][primary.id][:object_hash])
63+
when Resource then primary_objects.push(@included_objects[primary.class._type][primary.id][:object_hash])
64+
else raise "Unknown source type #{primary.inspect}"
65+
end
66+
end
67+
end
68+
else
69+
if source.try(:id)
70+
case source
71+
when CachedResourceFragment then primary_objects.push(@included_objects[source.type][source.id][:object_hash])
72+
when Resource then primary_objects.push(@included_objects[source.class._type][source.id][:object_hash])
73+
else raise "Unknown source type #{source.inspect}"
74+
end
75+
end
76+
end
77+
78+
included_objects = []
5779
@included_objects.each_value do |objects|
5880
objects.each_value do |object|
59-
if object[:primary]
60-
primary_objects.push(object[:object_hash])
61-
else
81+
unless object[:primary]
6282
included_objects.push(object[:object_hash])
6383
end
6484
end
@@ -168,9 +188,9 @@ def object_hash(source, include_directives = {})
168188
# requested includes. Fields are controlled fields option for each resource type, such
169189
# as fields: { people: [:id, :email, :comments], posts: [:id, :title, :author], comments: [:id, :body, :post]}
170190
# The fields options controls both fields and included links references.
171-
def process_primary(source, include_directives)
191+
def process_source_objects(source, include_directives)
172192
if source.respond_to?(:to_ary)
173-
source.each { |resource| process_primary(resource, include_directives) }
193+
source.each { |resource| process_source_objects(resource, include_directives) }
174194
else
175195
return {} if source.nil?
176196
add_resource(source, include_directives, true)

test/controllers/controller_test.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ def test_sorting_by_relationship_field
423423
assert_cacheable_get :index, params: {sort: 'author.name'}
424424

425425
assert_response :success
426-
assert json_response['data'].length > 10, 'there are enough recordsto show sort'
426+
assert json_response['data'].length > 10, 'there are enough records to show sort'
427427
assert_equal '17', json_response['data'][0]['id'], 'nil is at the top'
428428
assert_equal post.id.to_s, json_response['data'][1]['id'], 'alphabetically first user is second'
429429
end
@@ -438,6 +438,16 @@ def test_desc_sorting_by_relationship_field
438438
assert_equal post.id.to_s, json_response['data'][-2]['id'], 'alphabetically first user is second last'
439439
end
440440

441+
def test_sorting_by_relationship_field_include
442+
post = create_alphabetically_first_user_and_post
443+
assert_cacheable_get :index, params: {include: 'author', sort: 'author.name'}
444+
445+
assert_response :success
446+
assert json_response['data'].length > 10, 'there are enough records to show sort'
447+
assert_equal '17', json_response['data'][0]['id'], 'nil is at the top'
448+
assert_equal post.id.to_s, json_response['data'][1]['id'], 'alphabetically first user is second'
449+
end
450+
441451
def test_invalid_sort_param
442452
assert_cacheable_get :index, params: {sort: 'asdfg'}
443453

@@ -1921,6 +1931,15 @@ def test_tags_show_multiple_with_nonexistent_ids_at_the_beginning
19211931
assert_response :bad_request
19221932
assert_match /99,9,100 is not a valid value for id/, response.body
19231933
end
1934+
1935+
def test_nested_includes_sort
1936+
assert_cacheable_get :index, params: {filter: {id: '6,7,8,9'},
1937+
include: 'posts.tags,posts.author.posts',
1938+
sort: 'name'}
1939+
assert_response :success
1940+
assert_equal 4, json_response['data'].size
1941+
assert_equal 3, json_response['included'].size
1942+
end
19241943
end
19251944

19261945
class PicturesControllerTest < ActionController::TestCase

test/fixtures/active_record.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,10 +1138,6 @@ class PlanetResource < JSONAPI::Resource
11381138
has_one :planet_type
11391139

11401140
has_many :tags, acts_as_set: true
1141-
1142-
def records_for_moons(opts = {})
1143-
Moon.joins(:craters).select('moons.*, craters.code').distinct
1144-
end
11451141
end
11461142

11471143
class PropertyResource < JSONAPI::Resource

0 commit comments

Comments
 (0)