jsonapi-resources 0.9.7 → 0.9.12
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 +4 -4
- data/lib/jsonapi/acts_as_resource_controller.rb +2 -1
- data/lib/jsonapi/configuration.rb +10 -1
- data/lib/jsonapi/link_builder.rb +82 -112
- data/lib/jsonapi/relationship.rb +13 -3
- data/lib/jsonapi/request_parser.rb +2 -2
- data/lib/jsonapi/resource.rb +25 -14
- data/lib/jsonapi/resource_controller_metal.rb +2 -2
- data/lib/jsonapi/resource_serializer.rb +18 -11
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/routing_ext.rb +10 -2
- metadata +21 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfb7891ac7686be582e0831afd808f08504e492998968e704de2086c1656e9af
|
4
|
+
data.tar.gz: edeb27a90bec0a6fc79f67e0311cdf7e588fdcf347426489c21d94bcd40a3f28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 645534a3b1811e939fb6e36098e7624072793b59a39eecc99b05743ff77e91289ca6b35441c614220833049b689f8bcf7b6b6fb9fb1f09190b239b706b3d2da7
|
7
|
+
data.tar.gz: 7b562179f5f6ab17179c71208838fccaa1703d6c88eb99356075daa255a57242f59972e5ba0118740d4d80f7bc5706f2f87b4e99b0840cca32d00b19056f5712
|
@@ -125,7 +125,8 @@ module JSONAPI
|
|
125
125
|
base_url: base_url,
|
126
126
|
key_formatter: key_formatter,
|
127
127
|
route_formatter: route_formatter,
|
128
|
-
serialization_options: serialization_options
|
128
|
+
serialization_options: serialization_options,
|
129
|
+
controller: self
|
129
130
|
)
|
130
131
|
@resource_serializer
|
131
132
|
end
|
@@ -33,7 +33,8 @@ module JSONAPI
|
|
33
33
|
:resource_cache,
|
34
34
|
:default_resource_cache_field,
|
35
35
|
:resource_cache_digest_function,
|
36
|
-
:resource_cache_usage_report_function
|
36
|
+
:resource_cache_usage_report_function,
|
37
|
+
:default_exclude_links
|
37
38
|
|
38
39
|
def initialize
|
39
40
|
#:underscored_key, :camelized_key, :dasherized_key, or custom
|
@@ -134,6 +135,12 @@ module JSONAPI
|
|
134
135
|
# Optionally provide a callable which JSONAPI will call with information about cache
|
135
136
|
# performance. Should accept three arguments: resource name, hits count, misses count.
|
136
137
|
self.resource_cache_usage_report_function = nil
|
138
|
+
|
139
|
+
# Global configuration for links exclusion
|
140
|
+
# Controls whether to generate links like `self`, `related` with all the resources
|
141
|
+
# and relationships. Accepts either `:default`, `:none`, or array containing the
|
142
|
+
# specific default links to exclude, which may be `:self` and `:related`.
|
143
|
+
self.default_exclude_links = :none
|
137
144
|
end
|
138
145
|
|
139
146
|
def cache_formatters=(bool)
|
@@ -249,6 +256,8 @@ module JSONAPI
|
|
249
256
|
attr_writer :resource_cache_digest_function
|
250
257
|
|
251
258
|
attr_writer :resource_cache_usage_report_function
|
259
|
+
|
260
|
+
attr_writer :default_exclude_links
|
252
261
|
end
|
253
262
|
|
254
263
|
class << self
|
data/lib/jsonapi/link_builder.rb
CHANGED
@@ -2,23 +2,24 @@ module JSONAPI
|
|
2
2
|
class LinkBuilder
|
3
3
|
attr_reader :base_url,
|
4
4
|
:primary_resource_klass,
|
5
|
+
:route_formatter,
|
5
6
|
:engine,
|
6
|
-
:
|
7
|
+
:engine_mount_point,
|
8
|
+
:url_helpers
|
9
|
+
|
10
|
+
@@url_helper_methods = {}
|
7
11
|
|
8
12
|
def initialize(config = {})
|
9
|
-
@base_url
|
13
|
+
@base_url = config[:base_url]
|
10
14
|
@primary_resource_klass = config[:primary_resource_klass]
|
11
|
-
@
|
12
|
-
|
13
|
-
|
14
|
-
@routes = @engine.routes
|
15
|
-
else
|
16
|
-
@routes = Rails.application.routes
|
17
|
-
end
|
15
|
+
@route_formatter = config[:route_formatter]
|
16
|
+
@engine = build_engine
|
17
|
+
@engine_mount_point = @engine ? @engine.routes.find_script_name({}) : ""
|
18
18
|
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
19
|
+
# url_helpers may be either a controller which has the route helper methods, or the application router's
|
20
|
+
# url helpers module, `Rails.application.routes.url_helpers`. Because the method no longer behaves as a
|
21
|
+
# singleton, and it's expensive to generate the module, the controller is preferred.
|
22
|
+
@url_helpers = config[:url_helpers]
|
22
23
|
end
|
23
24
|
|
24
25
|
def engine?
|
@@ -26,50 +27,60 @@ module JSONAPI
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def primary_resources_url
|
29
|
-
@
|
30
|
-
|
31
|
-
|
30
|
+
if @primary_resource_klass._routed
|
31
|
+
primary_resources_path = resources_path(primary_resource_klass)
|
32
|
+
@primary_resources_url_cached ||= "#{ base_url }#{ serialized_engine_mount_point }#{ primary_resources_path }"
|
33
|
+
else
|
34
|
+
if JSONAPI.configuration.warn_on_missing_routes && !@primary_resource_klass._warned_missing_route
|
35
|
+
warn "primary_resources_url for #{@primary_resource_klass} could not be generated"
|
36
|
+
@primary_resource_klass._warned_missing_route = true
|
37
|
+
end
|
38
|
+
nil
|
39
|
+
end
|
32
40
|
end
|
33
41
|
|
34
42
|
def query_link(query_params)
|
35
|
-
|
43
|
+
url = primary_resources_url
|
44
|
+
return url if url.nil?
|
45
|
+
"#{ url }?#{ query_params.to_query }"
|
36
46
|
end
|
37
47
|
|
38
48
|
def relationships_related_link(source, relationship, query_params = {})
|
39
|
-
if relationship.
|
40
|
-
|
41
|
-
url =
|
49
|
+
if relationship._routed
|
50
|
+
url = "#{ self_link(source) }/#{ route_for_relationship(relationship) }"
|
51
|
+
url = "#{ url }?#{ query_params.to_query }" if query_params.present?
|
52
|
+
url
|
42
53
|
else
|
43
|
-
|
44
|
-
|
54
|
+
if JSONAPI.configuration.warn_on_missing_routes && !relationship._warned_missing_route
|
55
|
+
warn "related_link for #{relationship} could not be generated"
|
56
|
+
relationship._warned_missing_route = true
|
57
|
+
end
|
58
|
+
nil
|
45
59
|
end
|
46
|
-
|
47
|
-
url = "#{ base_url }#{ url }"
|
48
|
-
url = "#{ url }?#{ query_params.to_query }" if query_params.present?
|
49
|
-
url
|
50
|
-
rescue NoMethodError
|
51
|
-
warn "related_link for #{relationship} could not be generated" if JSONAPI.configuration.warn_on_missing_routes
|
52
60
|
end
|
53
61
|
|
54
62
|
def relationships_self_link(source, relationship)
|
55
|
-
if relationship.
|
56
|
-
|
57
|
-
url = call_url_helper(url_helper_name)
|
63
|
+
if relationship._routed
|
64
|
+
"#{ self_link(source) }/relationships/#{ route_for_relationship(relationship) }"
|
58
65
|
else
|
59
|
-
|
60
|
-
|
66
|
+
if JSONAPI.configuration.warn_on_missing_routes && !relationship._warned_missing_route
|
67
|
+
warn "self_link for #{relationship} could not be generated"
|
68
|
+
relationship._warned_missing_route = true
|
69
|
+
end
|
70
|
+
nil
|
61
71
|
end
|
62
|
-
|
63
|
-
url = "#{ base_url }#{ url }"
|
64
|
-
url
|
65
|
-
rescue NoMethodError
|
66
|
-
warn "self_link for #{relationship} could not be generated" if JSONAPI.configuration.warn_on_missing_routes
|
67
72
|
end
|
68
73
|
|
69
74
|
def self_link(source)
|
70
|
-
|
71
|
-
|
72
|
-
|
75
|
+
if source.class._routed
|
76
|
+
resource_url(source)
|
77
|
+
else
|
78
|
+
if JSONAPI.configuration.warn_on_missing_routes && !source.class._warned_missing_route
|
79
|
+
warn "self_link for #{source.class} could not be generated"
|
80
|
+
source.class._warned_missing_route = true
|
81
|
+
end
|
82
|
+
nil
|
83
|
+
end
|
73
84
|
end
|
74
85
|
|
75
86
|
private
|
@@ -81,6 +92,7 @@ module JSONAPI
|
|
81
92
|
unless scopes.empty?
|
82
93
|
"#{ scopes.first.to_s.camelize }::Engine".safe_constantize
|
83
94
|
end
|
95
|
+
|
84
96
|
# :nocov:
|
85
97
|
rescue LoadError => _e
|
86
98
|
nil
|
@@ -88,96 +100,54 @@ module JSONAPI
|
|
88
100
|
end
|
89
101
|
end
|
90
102
|
|
91
|
-
def
|
92
|
-
|
93
|
-
rescue NoMethodError => e
|
94
|
-
raise e
|
103
|
+
def format_route(route)
|
104
|
+
route_formatter.format(route)
|
95
105
|
end
|
96
106
|
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
107
|
+
def formatted_module_path_from_class(klass)
|
108
|
+
@_module_path_cache ||= {}
|
109
|
+
@_module_path_cache[klass] ||= begin
|
110
|
+
scopes = if @engine
|
111
|
+
module_scopes_from_class(klass)[1..-1]
|
112
|
+
else
|
113
|
+
module_scopes_from_class(klass)
|
114
|
+
end
|
101
115
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
call_url_helper(url_helper_name, source.id)
|
116
|
+
unless scopes.empty?
|
117
|
+
"/#{ scopes.map {|scope| format_route(scope.to_s.underscore)}.compact.join('/') }/"
|
118
|
+
else
|
119
|
+
"/"
|
120
|
+
end
|
108
121
|
end
|
109
122
|
end
|
110
123
|
|
111
|
-
def
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
def url_helper_name_from_parts(parts)
|
116
|
-
(parts << "path").reject(&:blank?).join("_")
|
124
|
+
def module_scopes_from_class(klass)
|
125
|
+
klass.name.to_s.split("::")[0...-1]
|
117
126
|
end
|
118
127
|
|
119
|
-
def
|
120
|
-
|
121
|
-
scopes = module_scopes_from_class(klass)[1..-1]
|
122
|
-
else
|
123
|
-
scopes = module_scopes_from_class(klass)
|
124
|
-
end
|
125
|
-
|
126
|
-
base_path_name = scopes.map { |scope| scope.underscore }.join("_")
|
127
|
-
end_path_name = klass._type.to_s
|
128
|
-
[base_path_name, end_path_name]
|
128
|
+
def resources_path(source_klass)
|
129
|
+
formatted_module_path_from_class(source_klass) + format_route(source_klass._type.to_s)
|
129
130
|
end
|
130
131
|
|
131
|
-
def
|
132
|
-
|
133
|
-
end
|
132
|
+
def resource_path(source)
|
133
|
+
url = "#{resources_path(source.class)}"
|
134
134
|
|
135
|
-
|
136
|
-
|
137
|
-
scopes = module_scopes_from_class(klass)[1..-1]
|
138
|
-
else
|
139
|
-
scopes = module_scopes_from_class(klass)
|
135
|
+
unless source.class.singleton?
|
136
|
+
url = "#{url}/#{source.id}"
|
140
137
|
end
|
141
|
-
|
142
|
-
base_path_name = scopes.map { |scope| scope.underscore }.join("_")
|
143
|
-
end_path_name = klass._type.to_s.singularize
|
144
|
-
[base_path_name, end_path_name]
|
145
|
-
end
|
146
|
-
|
147
|
-
def resource_url_helper_name_from_source(source)
|
148
|
-
url_helper_name_from_parts(resource_path_parts_from_class(source.class))
|
149
|
-
end
|
150
|
-
|
151
|
-
def related_url_helper_name(relationship)
|
152
|
-
relationship_parts = resource_path_parts_from_class(relationship.parent_resource)
|
153
|
-
relationship_parts << relationship.name
|
154
|
-
url_helper_name_from_parts(relationship_parts)
|
155
|
-
end
|
156
|
-
|
157
|
-
def singleton_related_url_helper_name(relationship)
|
158
|
-
relationship_parts = []
|
159
|
-
relationship_parts << relationship.name
|
160
|
-
relationship_parts += resource_path_parts_from_class(relationship.parent_resource)
|
161
|
-
url_helper_name_from_parts(relationship_parts)
|
138
|
+
url
|
162
139
|
end
|
163
140
|
|
164
|
-
def
|
165
|
-
|
166
|
-
relationship_parts << "relationships"
|
167
|
-
relationship_parts << relationship.name
|
168
|
-
url_helper_name_from_parts(relationship_parts)
|
141
|
+
def resource_url(source)
|
142
|
+
"#{ base_url }#{ serialized_engine_mount_point }#{ resource_path(source) }"
|
169
143
|
end
|
170
144
|
|
171
|
-
def
|
172
|
-
|
173
|
-
relationship_parts << "relationships"
|
174
|
-
relationship_parts << relationship.name
|
175
|
-
relationship_parts += resource_path_parts_from_class(relationship.parent_resource)
|
176
|
-
url_helper_name_from_parts(relationship_parts)
|
145
|
+
def serialized_engine_mount_point
|
146
|
+
engine_mount_point == "/" ? "" : engine_mount_point
|
177
147
|
end
|
178
148
|
|
179
|
-
def
|
180
|
-
|
149
|
+
def route_for_relationship(relationship)
|
150
|
+
format_route(relationship.name)
|
181
151
|
end
|
182
152
|
end
|
183
153
|
end
|
data/lib/jsonapi/relationship.rb
CHANGED
@@ -4,6 +4,8 @@ module JSONAPI
|
|
4
4
|
:class_name, :polymorphic, :always_include_linkage_data,
|
5
5
|
:parent_resource, :eager_load_on_include
|
6
6
|
|
7
|
+
attr_accessor :_routed, :_warned_missing_route
|
8
|
+
|
7
9
|
def initialize(name, options = {})
|
8
10
|
@name = name.to_s
|
9
11
|
@options = options
|
@@ -14,8 +16,10 @@ module JSONAPI
|
|
14
16
|
@polymorphic = options.fetch(:polymorphic, false) == true
|
15
17
|
@always_include_linkage_data = options.fetch(:always_include_linkage_data, false) == true
|
16
18
|
@eager_load_on_include = options.fetch(:eager_load_on_include, true) == true
|
19
|
+
@_routed = false
|
20
|
+
@_warned_missing_route = false
|
17
21
|
|
18
|
-
exclude_links(options.fetch(:exclude_links,
|
22
|
+
exclude_links(options.fetch(:exclude_links, JSONAPI.configuration.default_exclude_links))
|
19
23
|
end
|
20
24
|
|
21
25
|
alias_method :polymorphic?, :polymorphic
|
@@ -51,8 +55,14 @@ module JSONAPI
|
|
51
55
|
|
52
56
|
def type_for_source(source)
|
53
57
|
if polymorphic?
|
54
|
-
resource
|
55
|
-
|
58
|
+
# try polymorphic type column before asking it from the resource record
|
59
|
+
if source._model.respond_to?(polymorphic_type)
|
60
|
+
model_type = source._model.send(polymorphic_type)
|
61
|
+
source.class.resource_for(model_type)._type if model_type
|
62
|
+
else
|
63
|
+
resource = source.public_send(name)
|
64
|
+
resource.class._type if resource
|
65
|
+
end
|
56
66
|
else
|
57
67
|
type
|
58
68
|
end
|
@@ -291,7 +291,7 @@ module JSONAPI
|
|
291
291
|
return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
|
292
292
|
end
|
293
293
|
|
294
|
-
verified_filter = relationship.resource_klass.verify_filters(filter_method => value)
|
294
|
+
verified_filter = relationship.resource_klass.verify_filters({ filter_method => value }, @context)
|
295
295
|
@include_directives.merge_filter(relationship.name, verified_filter)
|
296
296
|
else
|
297
297
|
return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
|
@@ -314,7 +314,7 @@ module JSONAPI
|
|
314
314
|
|
315
315
|
sorts = []
|
316
316
|
begin
|
317
|
-
raw = URI.unescape(sort_criteria)
|
317
|
+
raw = URI::DEFAULT_PARSER.unescape(sort_criteria)
|
318
318
|
sorts += CSV.parse_line(raw)
|
319
319
|
rescue CSV::MalformedCSVError
|
320
320
|
fail JSONAPI::Exceptions::InvalidSortCriteria.new(format_key(@resource_klass._type), raw)
|
data/lib/jsonapi/resource.rb
CHANGED
@@ -5,6 +5,9 @@ module JSONAPI
|
|
5
5
|
class Resource
|
6
6
|
include Callbacks
|
7
7
|
|
8
|
+
DEFAULT_ATTRIBUTE_OPTIONS = { format: :default }.freeze
|
9
|
+
MODULE_PATH_REGEXP = /::[^:]+\Z/.freeze
|
10
|
+
|
8
11
|
attr_reader :context
|
9
12
|
|
10
13
|
define_jsonapi_resources_callbacks :create,
|
@@ -372,7 +375,7 @@ module JSONAPI
|
|
372
375
|
|
373
376
|
@reload_needed = true
|
374
377
|
else
|
375
|
-
@model.public_send(relationship.relation_name(context: @context)).
|
378
|
+
@model.public_send(relationship.relation_name(context: @context)).delete(key)
|
376
379
|
end
|
377
380
|
|
378
381
|
:completed
|
@@ -457,6 +460,9 @@ module JSONAPI
|
|
457
460
|
end
|
458
461
|
|
459
462
|
check_reserved_resource_name(subclass._type, subclass.name)
|
463
|
+
|
464
|
+
subclass._routed = false
|
465
|
+
subclass._warned_missing_route = false
|
460
466
|
end
|
461
467
|
|
462
468
|
def rebuild_relationships(relationships)
|
@@ -502,7 +508,7 @@ module JSONAPI
|
|
502
508
|
end
|
503
509
|
end
|
504
510
|
|
505
|
-
attr_accessor :_attributes, :_relationships, :_type, :_model_hints
|
511
|
+
attr_accessor :_attributes, :_relationships, :_type, :_model_hints, :_routed, :_warned_missing_route
|
506
512
|
attr_writer :_allowed_filters, :_paginator
|
507
513
|
|
508
514
|
def create(context)
|
@@ -552,7 +558,7 @@ module JSONAPI
|
|
552
558
|
end
|
553
559
|
|
554
560
|
def default_attribute_options
|
555
|
-
|
561
|
+
DEFAULT_ATTRIBUTE_OPTIONS
|
556
562
|
end
|
557
563
|
|
558
564
|
def relationship(*attrs)
|
@@ -680,7 +686,7 @@ module JSONAPI
|
|
680
686
|
include_directives = options[:include_directives]
|
681
687
|
if include_directives
|
682
688
|
model_includes = resolve_relationship_names_to_relations(self, include_directives.model_includes, options)
|
683
|
-
records = records.includes(model_includes)
|
689
|
+
records = records.includes(model_includes) if model_includes.present?
|
684
690
|
end
|
685
691
|
|
686
692
|
records
|
@@ -1066,6 +1072,18 @@ module JSONAPI
|
|
1066
1072
|
end
|
1067
1073
|
|
1068
1074
|
def exclude_links(exclude)
|
1075
|
+
_resolve_exclude_links(exclude)
|
1076
|
+
end
|
1077
|
+
|
1078
|
+
def _exclude_links
|
1079
|
+
@_exclude_links ||= _resolve_exclude_links(JSONAPI.configuration.default_exclude_links)
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
def exclude_link?(link)
|
1083
|
+
_exclude_links.include?(link.to_sym)
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
def _resolve_exclude_links(exclude)
|
1069
1087
|
case exclude
|
1070
1088
|
when :default, "default"
|
1071
1089
|
@_exclude_links = [:self]
|
@@ -1078,14 +1096,6 @@ module JSONAPI
|
|
1078
1096
|
end
|
1079
1097
|
end
|
1080
1098
|
|
1081
|
-
def _exclude_links
|
1082
|
-
@_exclude_links ||= []
|
1083
|
-
end
|
1084
|
-
|
1085
|
-
def exclude_link?(link)
|
1086
|
-
_exclude_links.include?(link.to_sym)
|
1087
|
-
end
|
1088
|
-
|
1089
1099
|
def caching(val = true)
|
1090
1100
|
@caching = val
|
1091
1101
|
end
|
@@ -1126,7 +1136,7 @@ module JSONAPI
|
|
1126
1136
|
if name == 'JSONAPI::Resource'
|
1127
1137
|
''
|
1128
1138
|
else
|
1129
|
-
name =~
|
1139
|
+
name =~ MODULE_PATH_REGEXP ? ($`.freeze.gsub('::', '/') + '/').underscore : ''
|
1130
1140
|
end
|
1131
1141
|
end
|
1132
1142
|
|
@@ -1344,7 +1354,8 @@ module JSONAPI
|
|
1344
1354
|
rel_id = row[index+1]
|
1345
1355
|
assoc_rels = res.preloaded_fragments[rel_name]
|
1346
1356
|
if index == path.length - 1
|
1347
|
-
|
1357
|
+
association_res = target_resources[klass.name].fetch(rel_id, nil)
|
1358
|
+
assoc_rels[rel_id] = association_res if association_res
|
1348
1359
|
else
|
1349
1360
|
res = assoc_rels[rel_id]
|
1350
1361
|
end
|
@@ -5,10 +5,10 @@ module JSONAPI
|
|
5
5
|
ActionController::Rendering,
|
6
6
|
ActionController::Renderers::All,
|
7
7
|
ActionController::StrongParameters,
|
8
|
-
ActionController::ForceSSL,
|
8
|
+
Gem::Requirement.new('< 6.1').satisfied_by?(ActionPack.gem_version) ? ActionController::ForceSSL : nil,
|
9
9
|
ActionController::Instrumentation,
|
10
10
|
JSONAPI::ActsAsResourceController
|
11
|
-
].freeze
|
11
|
+
].compact.freeze
|
12
12
|
|
13
13
|
MODULES.each do |mod|
|
14
14
|
include mod
|
@@ -287,7 +287,6 @@ module JSONAPI
|
|
287
287
|
include_linkage = ia && ia[:include]
|
288
288
|
include_linked_children = ia && !ia[:include_related].empty?
|
289
289
|
|
290
|
-
options = { filters: ia && ia[:include_filters] || {} }
|
291
290
|
if field_set.include?(name)
|
292
291
|
ro = relationship_object(source, relationship, include_linkage)
|
293
292
|
hash[format_key(name)] = ro unless ro.blank?
|
@@ -300,6 +299,7 @@ module JSONAPI
|
|
300
299
|
resources = if source.preloaded_fragments.has_key?(format_key(name))
|
301
300
|
source.preloaded_fragments[format_key(name)].values
|
302
301
|
else
|
302
|
+
options = { filters: ia && ia[:include_filters] || {} }
|
303
303
|
[source.public_send(name, options)].flatten(1).compact
|
304
304
|
end
|
305
305
|
resources.each do |resource|
|
@@ -418,6 +418,7 @@ module JSONAPI
|
|
418
418
|
[obj.type.underscore.pluralize, obj.id]
|
419
419
|
end
|
420
420
|
else
|
421
|
+
assoc = assoc.unscope(:includes) if assoc.is_a?(ActiveRecord::Relation)
|
421
422
|
assoc.pluck(:type, :id).map do |type, id|
|
422
423
|
[type.underscore.pluralize, id]
|
423
424
|
end
|
@@ -467,16 +468,20 @@ module JSONAPI
|
|
467
468
|
|
468
469
|
# Extracts the foreign key value for a to_one relationship.
|
469
470
|
def foreign_key_value(source, relationship)
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
source.
|
477
|
-
|
478
|
-
|
479
|
-
|
471
|
+
# If you have changed the key_name, don't even try to look at `"#{relationship.name}_id"`
|
472
|
+
# just load the association and call the custom key_name
|
473
|
+
foreign_key_type_changed = relationship.options[:foreign_key_type_changed] || false
|
474
|
+
related_resource_id =
|
475
|
+
if source.preloaded_fragments.has_key?(format_key(relationship.name))
|
476
|
+
source.preloaded_fragments[format_key(relationship.name)].values.first.try(:id)
|
477
|
+
elsif !foreign_key_type_changed && source.respond_to?("#{relationship.name}_id")
|
478
|
+
# If you have direct access to the underlying id, you don't have to load the relationship
|
479
|
+
# which can save quite a lot of time when loading a lot of data.
|
480
|
+
# This does not apply to e.g. has_one :through relationships.
|
481
|
+
source.public_send("#{relationship.name}_id")
|
482
|
+
else
|
483
|
+
source.public_send(relationship.name).try(:id)
|
484
|
+
end
|
480
485
|
return nil unless related_resource_id
|
481
486
|
@id_formatter.format(related_resource_id)
|
482
487
|
end
|
@@ -538,6 +543,8 @@ module JSONAPI
|
|
538
543
|
LinkBuilder.new(
|
539
544
|
base_url: options.fetch(:base_url, ''),
|
540
545
|
primary_resource_klass: primary_resource_klass,
|
546
|
+
route_formatter: options.fetch(:route_formatter, JSONAPI.configuration.route_formatter),
|
547
|
+
url_helpers: options.fetch(:url_helpers, options[:controller]),
|
541
548
|
)
|
542
549
|
end
|
543
550
|
end
|
data/lib/jsonapi/routing_ext.rb
CHANGED
@@ -20,6 +20,8 @@ module ActionDispatch
|
|
20
20
|
@resource_type = resources.first
|
21
21
|
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix(@resource_type))
|
22
22
|
|
23
|
+
res._routed = true
|
24
|
+
|
23
25
|
unless res.singleton?
|
24
26
|
warn "Singleton routes created for non singleton resource #{res}. Links may not be generated correctly."
|
25
27
|
end
|
@@ -84,6 +86,8 @@ module ActionDispatch
|
|
84
86
|
@resource_type = resources.first
|
85
87
|
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix(@resource_type))
|
86
88
|
|
89
|
+
res._routed = true
|
90
|
+
|
87
91
|
if res.singleton?
|
88
92
|
warn "Singleton resource #{res} should use `jsonapi_resource` instead."
|
89
93
|
end
|
@@ -223,6 +227,8 @@ module ActionDispatch
|
|
223
227
|
relationship_name = relationship.first
|
224
228
|
relationship = source._relationships[relationship_name]
|
225
229
|
|
230
|
+
relationship._routed = true
|
231
|
+
|
226
232
|
formatted_relationship_name = format_route(relationship.name)
|
227
233
|
|
228
234
|
if relationship.polymorphic?
|
@@ -235,7 +241,7 @@ module ActionDispatch
|
|
235
241
|
match formatted_relationship_name, controller: options[:controller],
|
236
242
|
relationship: relationship.name, source: resource_type_with_module_prefix(source._type),
|
237
243
|
action: 'get_related_resource', via: [:get],
|
238
|
-
as: relationship_name
|
244
|
+
as: "related/#{relationship_name}"
|
239
245
|
end
|
240
246
|
|
241
247
|
def jsonapi_related_resources(*relationship)
|
@@ -245,6 +251,8 @@ module ActionDispatch
|
|
245
251
|
relationship_name = relationship.first
|
246
252
|
relationship = source._relationships[relationship_name]
|
247
253
|
|
254
|
+
relationship._routed = true
|
255
|
+
|
248
256
|
formatted_relationship_name = format_route(relationship.name)
|
249
257
|
related_resource = JSONAPI::Resource.resource_for(resource_type_with_module_prefix(relationship.class_name.underscore))
|
250
258
|
options[:controller] ||= related_resource._type.to_s
|
@@ -253,7 +261,7 @@ module ActionDispatch
|
|
253
261
|
controller: options[:controller],
|
254
262
|
relationship: relationship.name, source: resource_type_with_module_prefix(source._type),
|
255
263
|
action: 'get_related_resources', via: [:get],
|
256
|
-
as: relationship_name
|
264
|
+
as: "related/#{relationship_name}"
|
257
265
|
end
|
258
266
|
|
259
267
|
protected
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi-resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Gebhardt
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-02-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '0'
|
21
21
|
type: :development
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- - "
|
25
|
+
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,6 +123,20 @@ dependencies:
|
|
123
123
|
- - ">="
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: memory_profiler
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
126
140
|
- !ruby/object:Gem::Dependency
|
127
141
|
name: activerecord
|
128
142
|
requirement: !ruby/object:Gem::Requirement
|
@@ -230,8 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
230
244
|
- !ruby/object:Gem::Version
|
231
245
|
version: '0'
|
232
246
|
requirements: []
|
233
|
-
|
234
|
-
rubygems_version: 2.7.6
|
247
|
+
rubygems_version: 3.0.3
|
235
248
|
signing_key:
|
236
249
|
specification_version: 4
|
237
250
|
summary: Easily support JSON API in Rails.
|