Skip to content

Commit 013d090

Browse files
committed
Allow Resource to set Resource Finder
Loads resource finder when found to be missing. This delayed loading enables the resource to set a resource finder that is used in place of the default. Removes the abstract methods from resource. These may vary based on the processor. Closes gh-1230
1 parent c50b1c5 commit 013d090

File tree

2 files changed

+36
-67
lines changed

2 files changed

+36
-67
lines changed

lib/jsonapi/resource.rb

Lines changed: 33 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -421,75 +421,21 @@ def inherited(subclass)
421421
subclass.attribute :id, format: :id, readonly: true
422422
end
423423

424-
check_reserved_resource_name(subclass._type, subclass.name)
425-
426-
subclass.include JSONAPI.configuration.default_resource_finder if JSONAPI.configuration.default_resource_finder
427-
end
428-
429-
# A ResourceFinder is a mixin that adds functionality to find Resources and Resource Fragments
430-
# to the core Resource class.
431-
#
432-
# Resource fragments are a hash with the following format:
433-
# {
434-
# identity: <required: a ResourceIdentity>,
435-
# cache: <optional: the resource's cache value>
436-
# attributes: <optional: attributes hash for attributes requested - currently unused>
437-
# related: {
438-
# <relationship_name>: <ResourceIdentity of a source resource in find_included_fragments>
439-
# }
440-
# }
441-
#
442-
# begin ResourceFinder Abstract methods
443-
def find(_filters, _options = {})
444-
# :nocov:
445-
raise 'Abstract ResourceFinder method called. Ensure that a ResourceFinder has been set.'
446-
# :nocov:
447-
end
448-
449-
def count(_filters, _options = {})
450-
# :nocov:
451-
raise 'Abstract ResourceFinder method called. Ensure that a ResourceFinder has been set.'
452-
# :nocov:
453-
end
454-
455-
def find_by_keys(_keys, _options = {})
456-
# :nocov:
457-
raise 'Abstract ResourceFinder method called. Ensure that a ResourceFinder has been set.'
458-
# :nocov:
459-
end
460-
461-
def find_by_key(_key, _options = {})
462-
# :nocov:
463-
raise 'Abstract ResourceFinder method called. Ensure that a ResourceFinder has been set.'
464-
# :nocov:
465-
end
466-
467-
def find_fragments(_filters, _options = {})
468-
# :nocov:
469-
raise 'Abstract ResourceFinder method called. Ensure that a ResourceFinder has been set.'
470-
# :nocov:
471-
end
472-
473-
def find_included_fragments(_source_rids, _relationship_name, _options = {})
474-
# :nocov:
475-
raise 'Abstract ResourceFinder method called. Ensure that a ResourceFinder has been set.'
476-
# :nocov:
477-
end
424+
# Ensure that the parent's resource finder is included before inheriting from the parent is completed
425+
if !_resource_finder_included && self != JSONAPI::Resource
426+
include_resource_finder
427+
end
428+
subclass._resource_finder_included = _resource_finder_included
478429

479-
def find_related_fragments(_source_rids, _relationship_name, _options = {})
480-
# :nocov:
481-
raise 'Abstract ResourceFinder method called. Ensure that a ResourceFinder has been set.'
482-
# :nocov:
430+
check_reserved_resource_name(subclass._type, subclass.name)
483431
end
484432

485-
def count_related(_source_rid, _relationship_name, _options = {})
486-
# :nocov:
487-
raise 'Abstract ResourceFinder method called. Ensure that a ResourceFinder has been set.'
488-
# :nocov:
433+
# Set the resource finder for a resource, which will override the default_resource_finder
434+
def resource_finder(resource_finder)
435+
@resource_finder = resource_finder
436+
include_resource_finder
489437
end
490438

491-
#end ResourceFinder Abstract methods
492-
493439
def rebuild_relationships(relationships)
494440
original_relationships = relationships.deep_dup
495441

@@ -534,7 +480,7 @@ def resource_type_for(model)
534480
end
535481
end
536482

537-
attr_accessor :_attributes, :_relationships, :_type, :_model_hints
483+
attr_accessor :_attributes, :_relationships, :_type, :_model_hints, :_resource_finder_included
538484
attr_writer :_allowed_filters, :_paginator, :_allowed_sort
539485

540486
def create(context)
@@ -1070,6 +1016,28 @@ def register_relationship(name, relationship_object)
10701016
end
10711017

10721018
private
1019+
def _resource_finder
1020+
@resource_finder ||= JSONAPI.configuration.default_resource_finder
1021+
end
1022+
1023+
def include_resource_finder
1024+
return if self == JSONAPI::Resource
1025+
if self._resource_finder_included
1026+
warn "#{self.name} is including a Resource Finder when one has already been included"
1027+
end
1028+
include _resource_finder
1029+
self._resource_finder_included = true
1030+
end
1031+
1032+
def method_missing(m, *args, &block)
1033+
if _resource_finder_included
1034+
super
1035+
else
1036+
# Handle the case where a resource finder has not been included yet. This should only happen once per class.
1037+
include_resource_finder
1038+
send(m, *args, &block)
1039+
end
1040+
end
10731041

10741042
def check_reserved_resource_name(type, name)
10751043
if [:ids, :types, :hrefs, :links].include?(type)

test/fixtures/active_record.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,8 +1557,10 @@ def find_breeds_by_keys(keys, options = {})
15571557
end
15581558
end
15591559

1560-
JSONAPI.configuration.default_resource_finder = BreedResourceFinder
15611560
class BreedResource < JSONAPI::Resource
1561+
1562+
resource_finder BreedResourceFinder
1563+
15621564
attribute :name, format: :title
15631565

15641566
# This is unneeded, just here for testing
@@ -1569,7 +1571,6 @@ def _save
15691571
return :accepted
15701572
end
15711573
end
1572-
JSONAPI.configuration.default_resource_finder = JSONAPI::ActiveRelationResourceFinder
15731574

15741575
class PlanetResource < JSONAPI::Resource
15751576
attribute :name

0 commit comments

Comments
 (0)