Skip to content

Commit d8b39c3

Browse files
committed
Merge pull request cerebris#38 from cerebris/pr/35
Fix N+1 issue with show multiple action - slight changes
2 parents 5714478 + 4c6d164 commit d8b39c3

File tree

4 files changed

+27
-8
lines changed

4 files changed

+27
-8
lines changed

lib/jsonapi/resource.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,18 @@ def find_by_key(key, options = {})
261261
self.new(model, context)
262262
end
263263

264+
def find_by_keys(keys, options = {})
265+
context = options[:context]
266+
_models = _model_class.where({_primary_key => keys})
267+
268+
unless _models.length == keys.length
269+
key = (keys - _models.pluck(:id).map(&:to_s)).first
270+
raise JSONAPI::Exceptions::RecordNotFound.new(key)
271+
end
272+
273+
_models.map { |model| self.new(model, context) }
274+
end
275+
264276
def verify_filters(filters, context = nil)
265277
verified_filters = {}
266278
filters.each do |filter, raw_value|

lib/jsonapi/resource_controller.rb

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,11 @@ def index
3030
def show
3131
keys = parse_key_array(params[resource_klass._primary_key])
3232

33-
if keys.length > 1
34-
resources = []
35-
keys.each do |key|
36-
resources.push(resource_klass.find_by_key(key, context: context))
37-
end
38-
else
39-
resources = resource_klass.find_by_key(keys[0], context: context)
40-
end
33+
resources = if keys.length > 1
34+
resource_klass.find_by_keys(keys, context: context)
35+
else
36+
resource_klass.find_by_key(keys[0], context: context)
37+
end
4138

4239
render json: JSONAPI::ResourceSerializer.new.serialize_to_hash(
4340
resources,

test/controllers/controller_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,12 @@ def test_tags_show_multiple_with_include
971971
assert_equal 4, json_response['tags'].size
972972
assert_equal 2, json_response['linked']['posts'].size
973973
end
974+
975+
def test_tags_show_multiple_with_nonexistent_ids
976+
get :show, {id: '6,99,9,100'}
977+
assert_response :not_found
978+
assert_match /The record identified by 99 could not be found./, json_response['errors'][0]['detail']
979+
end
974980
end
975981

976982
class ExpenseEntriesControllerTest < ActionController::TestCase

test/fixtures/active_record.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,10 @@ def self.find(attrs, options = {})
432432
def self.find_by_key(id, options = {})
433433
BreedResource.new($breed_data.breeds[id.to_i], options[:context])
434434
end
435+
436+
def self.find_by_keys(keys, options = {})
437+
keys.map { |key| self.find_by_key(key, options) }
438+
end
435439
end
436440

437441
class PlanetResource < JSONAPI::Resource

0 commit comments

Comments
 (0)