Skip to content

Commit 9f436b5

Browse files
bf4lgebhardt
andauthored
fix: allow multiple resource relation retrieval methods (#1425)
* fix: check if relation retrieval in included via included_modules * require 'jsonapi/relation_retrieval' * feat: raise when cannot include different retrieval strategy * test: multiple retrieval strategies --------- Co-authored-by: lgebhardt <larry@cerebris.com>
1 parent 2668b6b commit 9f436b5

7 files changed

+105
-8
lines changed

lib/jsonapi-resources.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require 'jsonapi/resources/railtie'
44
require 'jsonapi/naive_cache'
55
require 'jsonapi/compiled_json'
6+
require 'jsonapi/relation_retrieval'
67
require 'jsonapi/active_relation_retrieval'
78
require 'jsonapi/active_relation_retrieval_v09'
89
require 'jsonapi/active_relation_retrieval_v10'

lib/jsonapi/active_relation_retrieval.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module JSONAPI
44
module ActiveRelationRetrieval
5+
include ::JSONAPI::RelationRetrieval
6+
57
def find_related_ids(relationship, options = {})
68
self.class.find_related_fragments(self, relationship, options).keys.collect { |rid| rid.id }
79
end

lib/jsonapi/active_relation_retrieval_v09.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module JSONAPI
44
module ActiveRelationRetrievalV09
5+
include ::JSONAPI::RelationRetrieval
6+
57
def find_related_ids(relationship, options = {})
68
self.class.find_related_fragments(self.fragment, relationship, options).keys.collect { |rid| rid.id }
79
end

lib/jsonapi/active_relation_retrieval_v10.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module JSONAPI
44
module ActiveRelationRetrievalV10
5+
include ::JSONAPI::RelationRetrieval
6+
57
def find_related_ids(relationship, options = {})
68
self.class.find_related_fragments(self, relationship, options).keys.collect { |rid| rid.id }
79
end

lib/jsonapi/relation_retrieval.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
module JSONAPI
4+
module RelationRetrieval
5+
end
6+
end
7+

lib/jsonapi/resource_common.rb

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -431,19 +431,24 @@ def find_related_ids(relationship, options = {})
431431

432432
module ClassMethods
433433
def resource_retrieval_strategy(module_name = JSONAPI.configuration.default_resource_retrieval_strategy)
434-
if @_resource_retrieval_strategy_loaded
435-
warn "Resource retrieval strategy #{@_resource_retrieval_strategy_loaded} already loaded for #{self.name}"
436-
return
437-
end
438-
439434
module_name = module_name.to_s
440435

441436
return if module_name.blank? || module_name == 'self' || module_name == 'none'
442437

443-
class_eval do
444-
resource_retrieval_module = module_name.safe_constantize
445-
raise "Unable to find resource_retrieval_strategy #{module_name}" unless resource_retrieval_module
438+
resource_retrieval_module = module_name.safe_constantize
439+
440+
raise "Unable to find resource_retrieval_strategy #{module_name}" unless resource_retrieval_module
446441

442+
if included_modules.include?(::JSONAPI::RelationRetrieval)
443+
if _resource_retrieval_strategy_loaded.nil? || module_name == _resource_retrieval_strategy_loaded
444+
warn "Resource retrieval strategy #{module_name} already loaded for #{self.name}"
445+
return
446+
else
447+
fail ArgumentError.new("Resource retrieval strategy #{_resource_retrieval_strategy_loaded} already loaded for #{self.name}. Cannot load #{module_name}")
448+
end
449+
end
450+
451+
class_eval do
447452
include resource_retrieval_module
448453
extend "#{module_name}::ClassMethods".safe_constantize
449454
@_resource_retrieval_strategy_loaded = module_name
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
require File.expand_path('../../../test_helper', __FILE__)
2+
3+
module VX
4+
end
5+
6+
class MultipleActiveRelationResourceTest < ActiveSupport::TestCase
7+
def setup
8+
end
9+
10+
def teardown
11+
teardown_test_constant(::VX, :BaseResource)
12+
teardown_test_constant(::VX, :DuplicateSubBaseResource)
13+
teardown_test_constant(::VX, :InvalidSubBaseResource)
14+
teardown_test_constant(::VX, :ValidCustomBaseResource)
15+
end
16+
17+
def teardown_test_constant(namespace, constant_name)
18+
return unless namespace.const_defined?(constant_name)
19+
namespace.send(:remove_const, constant_name)
20+
rescue NameError
21+
end
22+
23+
def test_correct_resource_retrieval_strategy
24+
expected = 'JSONAPI::ActiveRelationRetrieval'
25+
default = JSONAPI.configuration.default_resource_retrieval_strategy
26+
assert_equal expected, default
27+
assert_nil JSONAPI::Resource._resource_retrieval_strategy_loaded
28+
29+
expected = 'JSONAPI::ActiveRelationRetrieval'
30+
assert_silent do
31+
::VX.module_eval <<~MODULE
32+
class BaseResource < JSONAPI::Resource
33+
abstract
34+
end
35+
MODULE
36+
end
37+
assert_equal expected, VX::BaseResource._resource_retrieval_strategy_loaded
38+
39+
strategy = 'JSONAPI::ActiveRelationRetrieval'
40+
expected = 'JSONAPI::ActiveRelationRetrieval'
41+
assert_output nil, "Resource retrieval strategy #{expected} already loaded for VX::DuplicateSubBaseResource\n" do
42+
::VX.module_eval <<~MODULE
43+
class DuplicateSubBaseResource < JSONAPI::Resource
44+
resource_retrieval_strategy '#{strategy}'
45+
abstract
46+
end
47+
MODULE
48+
end
49+
assert_equal expected, VX::DuplicateSubBaseResource._resource_retrieval_strategy_loaded
50+
51+
strategy = 'JSONAPI::ActiveRelationRetrievalV10'
52+
expected = "Resource retrieval strategy #{default} already loaded for VX::InvalidSubBaseResource. Cannot load #{strategy}"
53+
ex = assert_raises ArgumentError do
54+
::VX.module_eval <<~MODULE
55+
class InvalidSubBaseResource < JSONAPI::Resource
56+
resource_retrieval_strategy '#{strategy}'
57+
abstract
58+
end
59+
MODULE
60+
end
61+
assert_equal expected, ex.message
62+
63+
strategy = 'JSONAPI::ActiveRelationRetrievalV10'
64+
expected = 'JSONAPI::ActiveRelationRetrievalV10'
65+
assert_silent do
66+
::VX.module_eval <<~MODULE
67+
class ValidCustomBaseResource
68+
include JSONAPI::ResourceCommon
69+
root_resource
70+
abstract
71+
immutable
72+
resource_retrieval_strategy '#{strategy}'
73+
end
74+
MODULE
75+
end
76+
assert_equal expected, VX::ValidCustomBaseResource._resource_retrieval_strategy_loaded
77+
end
78+
end

0 commit comments

Comments
 (0)