jsonapi-resources 0.9.12 → 0.10.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/LICENSE.txt +1 -1
- data/README.md +34 -11
- data/lib/bug_report_templates/rails_5_latest.rb +125 -0
- data/lib/bug_report_templates/rails_5_master.rb +140 -0
- data/lib/jsonapi-resources.rb +8 -3
- data/lib/jsonapi/active_relation_resource_finder.rb +640 -0
- data/lib/jsonapi/active_relation_resource_finder/join_tree.rb +126 -0
- data/lib/jsonapi/acts_as_resource_controller.rb +121 -106
- data/lib/jsonapi/{cached_resource_fragment.rb → cached_response_fragment.rb} +13 -30
- data/lib/jsonapi/compiled_json.rb +11 -1
- data/lib/jsonapi/configuration.rb +44 -18
- data/lib/jsonapi/error.rb +27 -0
- data/lib/jsonapi/exceptions.rb +43 -40
- data/lib/jsonapi/formatter.rb +3 -3
- data/lib/jsonapi/include_directives.rb +2 -45
- data/lib/jsonapi/link_builder.rb +87 -80
- data/lib/jsonapi/operation.rb +16 -5
- data/lib/jsonapi/operation_result.rb +74 -16
- data/lib/jsonapi/processor.rb +233 -112
- data/lib/jsonapi/relationship.rb +77 -53
- data/lib/jsonapi/request_parser.rb +378 -423
- data/lib/jsonapi/resource.rb +224 -524
- data/lib/jsonapi/resource_controller_metal.rb +2 -2
- data/lib/jsonapi/resource_fragment.rb +47 -0
- data/lib/jsonapi/resource_id_tree.rb +112 -0
- data/lib/jsonapi/resource_identity.rb +42 -0
- data/lib/jsonapi/resource_serializer.rb +133 -301
- data/lib/jsonapi/resource_set.rb +108 -0
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +100 -88
- data/lib/jsonapi/routing_ext.rb +21 -43
- metadata +29 -45
- data/lib/jsonapi/operation_dispatcher.rb +0 -88
- data/lib/jsonapi/operation_results.rb +0 -35
- data/lib/jsonapi/relationship_builder.rb +0 -167
@@ -0,0 +1,108 @@
|
|
1
|
+
module JSONAPI
|
2
|
+
# Contains a hash of resource types which contain a hash of resources, relationships and primary status keyed by
|
3
|
+
# resource id.
|
4
|
+
class ResourceSet
|
5
|
+
|
6
|
+
attr_reader :resource_klasses, :populated
|
7
|
+
|
8
|
+
def initialize(resource_id_tree)
|
9
|
+
@populated = false
|
10
|
+
@resource_klasses = flatten_resource_id_tree(resource_id_tree)
|
11
|
+
end
|
12
|
+
|
13
|
+
def populate!(serializer, context, find_options)
|
14
|
+
@resource_klasses.each_key do |resource_klass|
|
15
|
+
missed_ids = []
|
16
|
+
|
17
|
+
serializer_config_key = serializer.config_key(resource_klass).gsub("/", "_")
|
18
|
+
context_json = resource_klass.attribute_caching_context(context).to_json
|
19
|
+
context_b64 = JSONAPI.configuration.resource_cache_digest_function.call(context_json)
|
20
|
+
context_key = "ATTR-CTX-#{context_b64.gsub("/", "_")}"
|
21
|
+
|
22
|
+
if resource_klass.caching?
|
23
|
+
cache_ids = []
|
24
|
+
|
25
|
+
@resource_klasses[resource_klass].each_pair do |k, v|
|
26
|
+
# Store the hashcode of the cache_field to avoid storing objects and to ensure precision isn't lost
|
27
|
+
# on timestamp types (i.e. string conversions dropping milliseconds)
|
28
|
+
cache_ids.push([k, resource_klass.hash_cache_field(v[:cache_id])])
|
29
|
+
end
|
30
|
+
|
31
|
+
found_resources = CachedResponseFragment.fetch_cached_fragments(
|
32
|
+
resource_klass,
|
33
|
+
serializer_config_key,
|
34
|
+
cache_ids,
|
35
|
+
context)
|
36
|
+
|
37
|
+
found_resources.each do |found_result|
|
38
|
+
resource = found_result[1]
|
39
|
+
if resource.nil?
|
40
|
+
missed_ids.push(found_result[0])
|
41
|
+
else
|
42
|
+
@resource_klasses[resource_klass][resource.id][:resource] = resource
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
missed_ids = @resource_klasses[resource_klass].keys
|
47
|
+
end
|
48
|
+
|
49
|
+
# fill in any missed resources
|
50
|
+
unless missed_ids.empty?
|
51
|
+
filters = {resource_klass._primary_key => missed_ids}
|
52
|
+
find_opts = {
|
53
|
+
context: context,
|
54
|
+
fields: find_options[:fields] }
|
55
|
+
|
56
|
+
found_resources = resource_klass.find(filters, find_opts)
|
57
|
+
|
58
|
+
found_resources.each do |resource|
|
59
|
+
relationship_data = @resource_klasses[resource_klass][resource.id][:relationships]
|
60
|
+
|
61
|
+
if resource_klass.caching?
|
62
|
+
(id, cr) = CachedResponseFragment.write(
|
63
|
+
resource_klass,
|
64
|
+
resource,
|
65
|
+
serializer,
|
66
|
+
serializer_config_key,
|
67
|
+
context,
|
68
|
+
context_key,
|
69
|
+
relationship_data)
|
70
|
+
|
71
|
+
@resource_klasses[resource_klass][id][:resource] = cr
|
72
|
+
else
|
73
|
+
@resource_klasses[resource_klass][resource.id][:resource] = resource
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
@populated = true
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def flatten_resource_id_tree(resource_id_tree, flattened_tree = {})
|
84
|
+
resource_id_tree.fragments.each_pair do |resource_rid, fragment|
|
85
|
+
|
86
|
+
resource_klass = resource_rid.resource_klass
|
87
|
+
id = resource_rid.id
|
88
|
+
|
89
|
+
flattened_tree[resource_klass] ||= {}
|
90
|
+
|
91
|
+
flattened_tree[resource_klass][id] ||= { primary: fragment.primary, relationships: {} }
|
92
|
+
flattened_tree[resource_klass][id][:cache_id] ||= fragment.cache
|
93
|
+
|
94
|
+
fragment.related.try(:each_pair) do |relationship_name, related_rids|
|
95
|
+
flattened_tree[resource_klass][id][:relationships][relationship_name] ||= Set.new
|
96
|
+
flattened_tree[resource_klass][id][:relationships][relationship_name].merge(related_rids)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
related_resource_id_trees = resource_id_tree.related_resource_id_trees
|
101
|
+
related_resource_id_trees.try(:each_value) do |related_resource_id_tree|
|
102
|
+
flatten_resource_id_tree(related_resource_id_tree, flattened_tree)
|
103
|
+
end
|
104
|
+
|
105
|
+
flattened_tree
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -1,86 +1,133 @@
|
|
1
1
|
module JSONAPI
|
2
2
|
class ResponseDocument
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
attr_reader :serialized_results
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@serialized_results = []
|
7
|
+
@result_codes = []
|
8
|
+
@error_results = []
|
9
|
+
@global_errors = []
|
10
|
+
|
6
11
|
@options = options
|
7
12
|
|
13
|
+
@top_level_meta = @options.fetch(:base_meta, {})
|
14
|
+
@top_level_links = @options.fetch(:base_links, {})
|
15
|
+
|
8
16
|
@key_formatter = @options.fetch(:key_formatter, JSONAPI.configuration.key_formatter)
|
9
17
|
end
|
10
18
|
|
11
|
-
def
|
12
|
-
|
19
|
+
def has_errors?
|
20
|
+
@error_results.length > 0 || @global_errors.length > 0
|
21
|
+
end
|
13
22
|
|
14
|
-
|
15
|
-
|
23
|
+
def add_result(result, operation)
|
24
|
+
if result.is_a?(JSONAPI::ErrorsOperationResult)
|
25
|
+
# Clear any serialized results
|
26
|
+
@serialized_results = []
|
16
27
|
|
17
|
-
|
18
|
-
|
28
|
+
# In JSONAPI v1 we only have one operation so all errors can be kept together
|
29
|
+
result.errors.each do |error|
|
30
|
+
add_global_error(error)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
@serialized_results.push result.to_hash(operation.options[:serializer])
|
34
|
+
@result_codes.push result.code.to_i
|
35
|
+
update_links(operation.options[:serializer], result)
|
36
|
+
update_meta(result)
|
37
|
+
end
|
38
|
+
end
|
19
39
|
|
20
|
-
|
40
|
+
def add_global_error(error)
|
41
|
+
@global_errors.push error
|
21
42
|
end
|
22
43
|
|
23
|
-
def
|
24
|
-
if
|
25
|
-
@
|
44
|
+
def contents
|
45
|
+
if has_errors?
|
46
|
+
return { 'errors' => @global_errors }
|
26
47
|
else
|
27
|
-
@
|
48
|
+
hash = @serialized_results[0]
|
49
|
+
meta = top_level_meta
|
50
|
+
hash.merge!('meta' => meta) unless meta.empty?
|
51
|
+
|
52
|
+
links = top_level_links
|
53
|
+
hash.merge!('links' => links) unless links.empty?
|
54
|
+
|
55
|
+
return hash
|
28
56
|
end
|
29
57
|
end
|
30
58
|
|
31
|
-
|
59
|
+
def status
|
60
|
+
status_codes = if has_errors?
|
61
|
+
@global_errors.collect do |error|
|
62
|
+
error.status.to_i
|
63
|
+
end
|
64
|
+
else
|
65
|
+
@result_codes
|
66
|
+
end
|
67
|
+
|
68
|
+
# Count the unique status codes
|
69
|
+
counts = status_codes.each_with_object(Hash.new(0)) { |code, counts| counts[code] += 1 }
|
70
|
+
|
71
|
+
# if there is only one status code we can return that
|
72
|
+
return counts.keys[0].to_i if counts.length == 1
|
73
|
+
|
74
|
+
# :nocov: not currently used
|
75
|
+
|
76
|
+
# if there are many we should return the highest general code, 200, 400, 500 etc.
|
77
|
+
max_status = 0
|
78
|
+
status_codes.each do |status|
|
79
|
+
code = status.to_i
|
80
|
+
max_status = code if max_status < code
|
81
|
+
end
|
82
|
+
return (max_status / 100).floor * 100
|
83
|
+
# :nocov:
|
84
|
+
end
|
32
85
|
|
33
|
-
|
34
|
-
# and the result of each operation. The keys are then formatted.
|
35
|
-
def top_level_meta
|
36
|
-
meta = @options.fetch(:base_meta, {})
|
86
|
+
private
|
37
87
|
|
38
|
-
|
88
|
+
def update_meta(result)
|
89
|
+
@top_level_meta.merge!(result.meta)
|
39
90
|
|
40
|
-
|
41
|
-
|
91
|
+
if JSONAPI.configuration.top_level_meta_include_record_count && result.respond_to?(:record_count)
|
92
|
+
@top_level_meta[JSONAPI.configuration.top_level_meta_record_count_key] = result.record_count
|
93
|
+
end
|
42
94
|
|
43
|
-
|
44
|
-
|
45
|
-
|
95
|
+
if JSONAPI.configuration.top_level_meta_include_page_count && result.respond_to?(:page_count)
|
96
|
+
@top_level_meta[JSONAPI.configuration.top_level_meta_page_count_key] = result.page_count
|
97
|
+
end
|
46
98
|
|
47
|
-
|
48
|
-
|
99
|
+
if result.warnings.any?
|
100
|
+
@top_level_meta[:warnings] = result.warnings.collect do |warning|
|
101
|
+
warning.to_hash
|
49
102
|
end
|
50
103
|
end
|
104
|
+
end
|
51
105
|
|
52
|
-
|
106
|
+
def top_level_meta
|
107
|
+
@top_level_meta.as_json.deep_transform_keys { |key| @key_formatter.format(key) }
|
53
108
|
end
|
54
109
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
relationship = result.source_resource.class._relationships[result._type.to_sym]
|
70
|
-
unless relationship.exclude_link?(link_name)
|
71
|
-
link = @serializer.link_builder.relationships_related_link(result.source_resource, relationship, query_params(params))
|
72
|
-
end
|
73
|
-
else
|
74
|
-
unless @serializer.link_builder.primary_resource_klass.exclude_link?(link_name)
|
75
|
-
link = @serializer.link_builder.query_link(query_params(params))
|
76
|
-
end
|
77
|
-
end
|
78
|
-
links[link_name] = link unless link.blank?
|
110
|
+
def update_links(serializer, result)
|
111
|
+
@top_level_links.merge!(result.links)
|
112
|
+
|
113
|
+
# Build pagination links
|
114
|
+
if result.is_a?(JSONAPI::ResourceSetOperationResult) ||
|
115
|
+
result.is_a?(JSONAPI::ResourcesSetOperationResult) ||
|
116
|
+
result.is_a?(JSONAPI::RelatedResourcesSetOperationResult)
|
117
|
+
|
118
|
+
result.pagination_params.each_pair do |link_name, params|
|
119
|
+
if result.is_a?(JSONAPI::RelatedResourcesSetOperationResult)
|
120
|
+
relationship = result.source_resource.class._relationships[result._type.to_sym]
|
121
|
+
@top_level_links[link_name] = serializer.link_builder.relationships_related_link(result.source_resource, relationship, query_params(params))
|
122
|
+
else
|
123
|
+
@top_level_links[link_name] = serializer.query_link(query_params(params))
|
79
124
|
end
|
80
125
|
end
|
81
126
|
end
|
127
|
+
end
|
82
128
|
|
83
|
-
|
129
|
+
def top_level_links
|
130
|
+
@top_level_links.deep_transform_keys { |key| @key_formatter.format(key) }
|
84
131
|
end
|
85
132
|
|
86
133
|
def query_params(params)
|
@@ -101,40 +148,5 @@ module JSONAPI
|
|
101
148
|
|
102
149
|
query_params
|
103
150
|
end
|
104
|
-
|
105
|
-
def results_to_hash
|
106
|
-
if @operation_results.has_errors?
|
107
|
-
{ errors: @operation_results.all_errors }
|
108
|
-
else
|
109
|
-
if @operation_results.results.length == 1
|
110
|
-
result = @operation_results.results[0]
|
111
|
-
|
112
|
-
case result
|
113
|
-
when JSONAPI::ResourceOperationResult
|
114
|
-
@serializer.serialize_to_hash(result.resource)
|
115
|
-
when JSONAPI::ResourcesOperationResult
|
116
|
-
@serializer.serialize_to_hash(result.resources)
|
117
|
-
when JSONAPI::RelationshipOperationResult
|
118
|
-
@serializer.serialize_to_relationship_hash(result.parent_resource,
|
119
|
-
result.relationship)
|
120
|
-
when JSONAPI::OperationResult
|
121
|
-
{}
|
122
|
-
end
|
123
|
-
|
124
|
-
elsif @operation_results.results.length > 1
|
125
|
-
resources = []
|
126
|
-
@operation_results.results.each do |result|
|
127
|
-
case result
|
128
|
-
when JSONAPI::ResourceOperationResult
|
129
|
-
resources.push(result.resource)
|
130
|
-
when JSONAPI::ResourcesOperationResult
|
131
|
-
resources.concat(result.resources)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
@serializer.serialize_to_hash(resources)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
151
|
end
|
140
152
|
end
|
data/lib/jsonapi/routing_ext.rb
CHANGED
@@ -18,13 +18,7 @@ module ActionDispatch
|
|
18
18
|
|
19
19
|
def jsonapi_resource(*resources, &_block)
|
20
20
|
@resource_type = resources.first
|
21
|
-
res = JSONAPI::Resource.
|
22
|
-
|
23
|
-
res._routed = true
|
24
|
-
|
25
|
-
unless res.singleton?
|
26
|
-
warn "Singleton routes created for non singleton resource #{res}. Links may not be generated correctly."
|
27
|
-
end
|
21
|
+
res = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix(@resource_type))
|
28
22
|
|
29
23
|
options = resources.extract_options!.dup
|
30
24
|
options[:controller] ||= @resource_type
|
@@ -39,8 +33,8 @@ module ActionDispatch
|
|
39
33
|
end
|
40
34
|
|
41
35
|
if res._immutable
|
42
|
-
options[:except] << :create
|
43
|
-
options[:except] << :update
|
36
|
+
options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create')
|
37
|
+
options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update')
|
44
38
|
options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy')
|
45
39
|
end
|
46
40
|
|
@@ -70,7 +64,7 @@ module ActionDispatch
|
|
70
64
|
end
|
71
65
|
|
72
66
|
def jsonapi_relationships(options = {})
|
73
|
-
res = JSONAPI::Resource.
|
67
|
+
res = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix(@resource_type))
|
74
68
|
res._relationships.each do |relationship_name, relationship|
|
75
69
|
if relationship.is_a?(JSONAPI::Relationship::ToMany)
|
76
70
|
jsonapi_links(relationship_name, options)
|
@@ -84,13 +78,7 @@ module ActionDispatch
|
|
84
78
|
|
85
79
|
def jsonapi_resources(*resources, &_block)
|
86
80
|
@resource_type = resources.first
|
87
|
-
res = JSONAPI::Resource.
|
88
|
-
|
89
|
-
res._routed = true
|
90
|
-
|
91
|
-
if res.singleton?
|
92
|
-
warn "Singleton resource #{res} should use `jsonapi_resource` instead."
|
93
|
-
end
|
81
|
+
res = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix(@resource_type))
|
94
82
|
|
95
83
|
options = resources.extract_options!.dup
|
96
84
|
options[:controller] ||= @resource_type
|
@@ -114,8 +102,8 @@ module ActionDispatch
|
|
114
102
|
end
|
115
103
|
|
116
104
|
if res._immutable
|
117
|
-
options[:except] << :create
|
118
|
-
options[:except] << :update
|
105
|
+
options[:except] << :create unless options[:except].include?(:create) || options[:except].include?('create')
|
106
|
+
options[:except] << :update unless options[:except].include?(:update) || options[:except].include?('update')
|
119
107
|
options[:except] << :destroy unless options[:except].include?(:destroy) || options[:except].include?('destroy')
|
120
108
|
end
|
121
109
|
|
@@ -159,28 +147,24 @@ module ActionDispatch
|
|
159
147
|
formatted_relationship_name = format_route(link_type)
|
160
148
|
options = links.extract_options!.dup
|
161
149
|
|
162
|
-
res = JSONAPI::Resource.
|
150
|
+
res = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix)
|
163
151
|
options[:controller] ||= res._type.to_s
|
164
152
|
|
165
153
|
methods = links_methods(options)
|
166
154
|
|
167
155
|
if methods.include?(:show)
|
168
|
-
match "relationships/#{formatted_relationship_name}",
|
169
|
-
|
170
|
-
action: 'show_relationship', relationship: link_type.to_s, via: [:get],
|
171
|
-
as: "relationships/#{link_type}"
|
156
|
+
match "relationships/#{formatted_relationship_name}", controller: options[:controller],
|
157
|
+
action: 'show_relationship', relationship: link_type.to_s, via: [:get]
|
172
158
|
end
|
173
159
|
|
174
160
|
if res.mutable?
|
175
161
|
if methods.include?(:update)
|
176
|
-
match "relationships/#{formatted_relationship_name}",
|
177
|
-
controller: options[:controller],
|
162
|
+
match "relationships/#{formatted_relationship_name}", controller: options[:controller],
|
178
163
|
action: 'update_relationship', relationship: link_type.to_s, via: [:put, :patch]
|
179
164
|
end
|
180
165
|
|
181
166
|
if methods.include?(:destroy)
|
182
|
-
match "relationships/#{formatted_relationship_name}",
|
183
|
-
controller: options[:controller],
|
167
|
+
match "relationships/#{formatted_relationship_name}", controller: options[:controller],
|
184
168
|
action: 'destroy_relationship', relationship: link_type.to_s, via: [:delete]
|
185
169
|
end
|
186
170
|
end
|
@@ -191,15 +175,14 @@ module ActionDispatch
|
|
191
175
|
formatted_relationship_name = format_route(link_type)
|
192
176
|
options = links.extract_options!.dup
|
193
177
|
|
194
|
-
res = JSONAPI::Resource.
|
178
|
+
res = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix)
|
195
179
|
options[:controller] ||= res._type.to_s
|
196
180
|
|
197
181
|
methods = links_methods(options)
|
198
182
|
|
199
183
|
if methods.include?(:show)
|
200
184
|
match "relationships/#{formatted_relationship_name}", controller: options[:controller],
|
201
|
-
action: 'show_relationship', relationship: link_type.to_s, via: [:get]
|
202
|
-
as: "relationships/#{link_type}"
|
185
|
+
action: 'show_relationship', relationship: link_type.to_s, via: [:get]
|
203
186
|
end
|
204
187
|
|
205
188
|
if res.mutable?
|
@@ -221,47 +204,41 @@ module ActionDispatch
|
|
221
204
|
end
|
222
205
|
|
223
206
|
def jsonapi_related_resource(*relationship)
|
224
|
-
source = JSONAPI::Resource.
|
207
|
+
source = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix)
|
225
208
|
options = relationship.extract_options!.dup
|
226
209
|
|
227
210
|
relationship_name = relationship.first
|
228
211
|
relationship = source._relationships[relationship_name]
|
229
212
|
|
230
|
-
relationship._routed = true
|
231
|
-
|
232
213
|
formatted_relationship_name = format_route(relationship.name)
|
233
214
|
|
234
215
|
if relationship.polymorphic?
|
235
216
|
options[:controller] ||= relationship.class_name.underscore.pluralize
|
236
217
|
else
|
237
|
-
related_resource = JSONAPI::Resource.
|
218
|
+
related_resource = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix(relationship.class_name.underscore.pluralize))
|
238
219
|
options[:controller] ||= related_resource._type.to_s
|
239
220
|
end
|
240
221
|
|
241
222
|
match formatted_relationship_name, controller: options[:controller],
|
242
223
|
relationship: relationship.name, source: resource_type_with_module_prefix(source._type),
|
243
|
-
action: '
|
244
|
-
as: "related/#{relationship_name}"
|
224
|
+
action: 'show_related_resource', via: [:get]
|
245
225
|
end
|
246
226
|
|
247
227
|
def jsonapi_related_resources(*relationship)
|
248
|
-
source = JSONAPI::Resource.
|
228
|
+
source = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix)
|
249
229
|
options = relationship.extract_options!.dup
|
250
230
|
|
251
231
|
relationship_name = relationship.first
|
252
232
|
relationship = source._relationships[relationship_name]
|
253
233
|
|
254
|
-
relationship._routed = true
|
255
|
-
|
256
234
|
formatted_relationship_name = format_route(relationship.name)
|
257
|
-
related_resource = JSONAPI::Resource.
|
235
|
+
related_resource = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix(relationship.class_name.underscore))
|
258
236
|
options[:controller] ||= related_resource._type.to_s
|
259
237
|
|
260
238
|
match formatted_relationship_name,
|
261
239
|
controller: options[:controller],
|
262
240
|
relationship: relationship.name, source: resource_type_with_module_prefix(source._type),
|
263
|
-
action: '
|
264
|
-
as: "related/#{relationship_name}"
|
241
|
+
action: 'index_related_resources', via: [:get]
|
265
242
|
end
|
266
243
|
|
267
244
|
protected
|
@@ -274,6 +251,7 @@ module ActionDispatch
|
|
274
251
|
@scope = @scope.parent
|
275
252
|
end
|
276
253
|
# :nocov:
|
254
|
+
|
277
255
|
private
|
278
256
|
|
279
257
|
def resource_type_with_module_prefix(resource = nil)
|