cerebris / jsonapi-resources

A resource-focused Rails library for developing JSON:API compliant servers.
http://jsonapi-resources.com
MIT License
2.32k stars 529 forks source link

UUIDResource has_many IdResource causes undefined method `[]` when doing GET [...]?includes= #1156

Open butchmarshall opened 6 years ago

butchmarshall commented 6 years ago

This issue is a (choose one):

Description

I've tracked the issue to lib/jsonapi/processor.rb:587.

resource_set[resource_klass] is holding the associated resources in an array key'd by a string {"1" => [...]} and attempting to access it via an int resource.id.

With the following resources just issue this get request (make sure to have include=).

GET /uuids/3bbaf722-4583-4fa6-ac36-9190d4b93f80?include=ids

class UuidResource < JSONAPI::Resource
  key_type :uuid
  has_many :ids
end

class IdResource < JSONAPI::Resource
  has_one :uuid
end

Throws error:

Internal Server Error: undefined method `[]' for nil:NilClass /var/lib/gems/2.3.0/bundler/gems/jsonapi-resources-d185ebb76cd2/lib/jsonapi/processor.rb:587:in `block (2 levels) in populate_resource_set'
/var/lib/gems/2.3.0/bundler/gems/jsonapi-resources-d185ebb76cd2/lib/jsonapi/processor.rb:586:in `each'
/var/lib/gems/2.3.0/bundler/gems/jsonapi-resources-d185ebb76cd2/lib/jsonapi/processor.rb:586:in `block in populate_resource_set'
/var/lib/gems/2.3.0/bundler/gems/jsonapi-resources-d185ebb76cd2/lib/jsonapi/processor.rb:542:in `each_key'
butchmarshall commented 6 years ago

And when I build a unit test for this it works fine... I'll re-check whats going on.

butchmarshall commented 6 years ago

Still not sure how to reproduce in unit tests.

This branch fixes my production code issue_1156

butchmarshall commented 6 years ago

Yep this is definitely an issue - I have pushed a unit test that fails.

If the top-level controller resource is a UUID then it will cast all the included resources primary keys as strings instead of integers.

Change that top level resource from UUID -> integer and the unit test will then pass.

The source_resource array has JSONAPI::ResourceIdentity objects that have primary keys as integers cast to strings, but the related_resource[:source_rids] JSONAPI::ResourceIdentity object it's using for lookup (process.rb lines 488 to 495 have a primary key as an integer.

If I force the ResourceIdentity to always cast the @id = id.tos then the test passes (but others fail)

It looks like active_relation_resource_finder.rb line 223 is the issue. records.pluck if will cast to a string /integer depending on whats there.

This is probably related to a Rails bug i found Unexpected Type Casting in ActiveRecord::Calculations#pluck #28044