jsonapi-resources 0.10.0.beta5 → 0.10.0.beta6
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/basic_resource.rb +14 -7
- data/lib/jsonapi/configuration.rb +10 -1
- data/lib/jsonapi/link_builder.rb +78 -117
- data/lib/jsonapi/relationship.rb +6 -1
- data/lib/jsonapi/resource_controller_metal.rb +3 -0
- data/lib/jsonapi/resource_serializer.rb +2 -0
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/routing_ext.rb +8 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ac7e65d3c40e15413e9d5a7552a8f871a2313c9f9d41f4cd520ab62f8e3c7d8
|
4
|
+
data.tar.gz: 7ba4da6469f82a35eee2df2e3475d6fb28f6b229bc78863f57c5c1576cf9973e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2ee268639e83ea3f490258f85ba8fe13785f31fd85d3a5b46cc92d7c340f3ba95f3316ca1dfcf2f33a92f31e17c023aa093d39d53b39d3c48cf8c9af22cd7ad
|
7
|
+
data.tar.gz: 76a30f8af5d5569cf40f979f296dc90e95a83f5f57b178c977ba8067755e20d5ac5e46f588f3bed4dddaf587faf7d6081e04b7116657af4d65faa6f858472a0f
|
@@ -102,7 +102,8 @@ module JSONAPI
|
|
102
102
|
base_url: base_url,
|
103
103
|
key_formatter: key_formatter,
|
104
104
|
route_formatter: route_formatter,
|
105
|
-
serialization_options: serialization_options
|
105
|
+
serialization_options: serialization_options,
|
106
|
+
controller: self
|
106
107
|
)
|
107
108
|
op.options[:cache_serializer_output] = !JSONAPI.configuration.resource_cache.nil?
|
108
109
|
|
@@ -365,7 +365,7 @@ module JSONAPI
|
|
365
365
|
|
366
366
|
@reload_needed = true
|
367
367
|
else
|
368
|
-
@model.public_send(relationship.relation_name(context: @context)).
|
368
|
+
@model.public_send(relationship.relation_name(context: @context)).delete(key)
|
369
369
|
end
|
370
370
|
|
371
371
|
:completed
|
@@ -448,6 +448,9 @@ module JSONAPI
|
|
448
448
|
end
|
449
449
|
|
450
450
|
check_reserved_resource_name(subclass._type, subclass.name)
|
451
|
+
|
452
|
+
subclass._routed = false
|
453
|
+
subclass._warned_missing_route = false
|
451
454
|
end
|
452
455
|
|
453
456
|
def rebuild_relationships(relationships)
|
@@ -494,7 +497,7 @@ module JSONAPI
|
|
494
497
|
end
|
495
498
|
end
|
496
499
|
|
497
|
-
attr_accessor :_attributes, :_relationships, :_type, :_model_hints
|
500
|
+
attr_accessor :_attributes, :_relationships, :_type, :_model_hints, :_routed, :_warned_missing_route
|
498
501
|
attr_writer :_allowed_filters, :_paginator, :_allowed_sort
|
499
502
|
|
500
503
|
def create(context)
|
@@ -960,21 +963,25 @@ module JSONAPI
|
|
960
963
|
!@immutable
|
961
964
|
end
|
962
965
|
|
963
|
-
def
|
966
|
+
def parse_exclude_links(exclude)
|
964
967
|
case exclude
|
965
968
|
when :default, "default"
|
966
|
-
|
969
|
+
[:self]
|
967
970
|
when :none, "none"
|
968
|
-
|
971
|
+
[]
|
969
972
|
when Array
|
970
|
-
|
973
|
+
exclude.collect {|link| link.to_sym}
|
971
974
|
else
|
972
975
|
fail "Invalid exclude_links"
|
973
976
|
end
|
974
977
|
end
|
975
978
|
|
979
|
+
def exclude_links(exclude)
|
980
|
+
@_exclude_links = parse_exclude_links(exclude)
|
981
|
+
end
|
982
|
+
|
976
983
|
def _exclude_links
|
977
|
-
@_exclude_links ||=
|
984
|
+
@_exclude_links ||= parse_exclude_links(JSONAPI.configuration.default_exclude_links)
|
978
985
|
end
|
979
986
|
|
980
987
|
def exclude_link?(link)
|
@@ -37,7 +37,8 @@ module JSONAPI
|
|
37
37
|
:default_caching,
|
38
38
|
:default_resource_cache_field,
|
39
39
|
:resource_cache_digest_function,
|
40
|
-
:resource_cache_usage_report_function
|
40
|
+
:resource_cache_usage_report_function,
|
41
|
+
:default_exclude_links
|
41
42
|
|
42
43
|
def initialize
|
43
44
|
#:underscored_key, :camelized_key, :dasherized_key, or custom
|
@@ -149,6 +150,12 @@ module JSONAPI
|
|
149
150
|
# Optionally provide a callable which JSONAPI will call with information about cache
|
150
151
|
# performance. Should accept three arguments: resource name, hits count, misses count.
|
151
152
|
self.resource_cache_usage_report_function = nil
|
153
|
+
|
154
|
+
# Global configuration for links exclusion
|
155
|
+
# Controls whether to generate links like `self`, `related` with all the resources
|
156
|
+
# and relationships. Accepts either `:default`, `:none`, or array containing the
|
157
|
+
# specific default links to exclude, which may be `:self` and `:related`.
|
158
|
+
self.default_exclude_links = :none
|
152
159
|
end
|
153
160
|
|
154
161
|
def cache_formatters=(bool)
|
@@ -276,6 +283,8 @@ module JSONAPI
|
|
276
283
|
attr_writer :resource_cache_digest_function
|
277
284
|
|
278
285
|
attr_writer :resource_cache_usage_report_function
|
286
|
+
|
287
|
+
attr_writer :default_exclude_links
|
279
288
|
end
|
280
289
|
|
281
290
|
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 }#{ 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,105 +92,55 @@ module JSONAPI
|
|
81
92
|
unless scopes.empty?
|
82
93
|
"#{ scopes.first.to_s.camelize }::Engine".safe_constantize
|
83
94
|
end
|
84
|
-
|
95
|
+
|
96
|
+
# :nocov:
|
85
97
|
rescue LoadError => _e
|
86
98
|
nil
|
87
|
-
|
99
|
+
# :nocov:
|
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
|
+
scopes = if @engine
|
109
|
+
module_scopes_from_class(klass)[1..-1]
|
110
|
+
else
|
111
|
+
module_scopes_from_class(klass)
|
112
|
+
end
|
101
113
|
|
102
|
-
|
103
|
-
|
104
|
-
if source.class.singleton?
|
105
|
-
call_url_helper(url_helper_name)
|
114
|
+
unless scopes.empty?
|
115
|
+
"/#{ scopes.map {|scope| format_route(scope.to_s.underscore)}.compact.join('/') }/"
|
106
116
|
else
|
107
|
-
|
117
|
+
"/"
|
108
118
|
end
|
109
119
|
end
|
110
120
|
|
111
|
-
def
|
112
|
-
|
121
|
+
def module_scopes_from_class(klass)
|
122
|
+
klass.name.to_s.split("::")[0...-1]
|
113
123
|
end
|
114
124
|
|
115
|
-
def
|
116
|
-
(
|
125
|
+
def resources_path(source_klass)
|
126
|
+
formatted_module_path_from_class(source_klass) + format_route(source_klass._type.to_s)
|
117
127
|
end
|
118
128
|
|
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]
|
129
|
-
end
|
130
|
-
|
131
|
-
def resources_url_helper_name_from_class(klass)
|
132
|
-
url_helper_name_from_parts(resources_path_parts_from_class(klass))
|
133
|
-
end
|
129
|
+
def resource_path(source)
|
130
|
+
url = "#{resources_path(source.class)}"
|
134
131
|
|
135
|
-
|
136
|
-
|
137
|
-
scopes = module_scopes_from_class(klass)[1..-1]
|
138
|
-
else
|
139
|
-
scopes = module_scopes_from_class(klass)
|
132
|
+
unless source.class.singleton?
|
133
|
+
url = "#{url}/#{source.id}"
|
140
134
|
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 << "related"
|
154
|
-
relationship_parts << relationship.name
|
155
|
-
url_helper_name_from_parts(relationship_parts)
|
156
|
-
end
|
157
|
-
|
158
|
-
def singleton_related_url_helper_name(relationship)
|
159
|
-
relationship_parts = []
|
160
|
-
relationship_parts << "related"
|
161
|
-
relationship_parts << relationship.name
|
162
|
-
relationship_parts += resource_path_parts_from_class(relationship.parent_resource)
|
163
|
-
url_helper_name_from_parts(relationship_parts)
|
164
|
-
end
|
165
|
-
|
166
|
-
def relationship_self_url_helper_name(relationship)
|
167
|
-
relationship_parts = resource_path_parts_from_class(relationship.parent_resource)
|
168
|
-
relationship_parts << "relationships"
|
169
|
-
relationship_parts << relationship.name
|
170
|
-
url_helper_name_from_parts(relationship_parts)
|
135
|
+
url
|
171
136
|
end
|
172
137
|
|
173
|
-
def
|
174
|
-
|
175
|
-
relationship_parts << "relationships"
|
176
|
-
relationship_parts << relationship.name
|
177
|
-
relationship_parts += resource_path_parts_from_class(relationship.parent_resource)
|
178
|
-
url_helper_name_from_parts(relationship_parts)
|
138
|
+
def resource_url(source)
|
139
|
+
"#{ base_url }#{ engine_mount_point }#{ resource_path(source) }"
|
179
140
|
end
|
180
141
|
|
181
|
-
def
|
182
|
-
|
142
|
+
def route_for_relationship(relationship)
|
143
|
+
format_route(relationship.name)
|
183
144
|
end
|
184
145
|
end
|
185
146
|
end
|
data/lib/jsonapi/relationship.rb
CHANGED
@@ -7,6 +7,8 @@ module JSONAPI
|
|
7
7
|
|
8
8
|
attr_writer :allow_include
|
9
9
|
|
10
|
+
attr_accessor :_routed, :_warned_missing_route
|
11
|
+
|
10
12
|
def initialize(name, options = {})
|
11
13
|
@name = name.to_s
|
12
14
|
@options = options
|
@@ -27,7 +29,10 @@ module JSONAPI
|
|
27
29
|
@class_name = nil
|
28
30
|
@inverse_relationship = nil
|
29
31
|
|
30
|
-
|
32
|
+
@_routed = false
|
33
|
+
@_warned_missing_route = false
|
34
|
+
|
35
|
+
exclude_links(options.fetch(:exclude_links, JSONAPI.configuration.default_exclude_links))
|
31
36
|
|
32
37
|
# Custom methods are reserved for future use
|
33
38
|
@custom_methods = options.fetch(:custom_methods, {})
|
@@ -10,6 +10,9 @@ module JSONAPI
|
|
10
10
|
JSONAPI::ActsAsResourceController
|
11
11
|
].freeze
|
12
12
|
|
13
|
+
# Note, the url_helpers are not loaded. This will prevent links from being generated for resources, and warnings
|
14
|
+
# will be emitted. Link support can be added by including `Rails.application.routes.url_helpers`, and links
|
15
|
+
# can be disabled, and warning suppressed, for a resource with `exclude_links :default`
|
13
16
|
MODULES.each do |mod|
|
14
17
|
include mod
|
15
18
|
end
|
@@ -381,6 +381,8 @@ module JSONAPI
|
|
381
381
|
LinkBuilder.new(
|
382
382
|
base_url: options.fetch(:base_url, ''),
|
383
383
|
primary_resource_klass: primary_resource_klass,
|
384
|
+
route_formatter: options.fetch(:route_formatter, JSONAPI.configuration.route_formatter),
|
385
|
+
url_helpers: options.fetch(:url_helpers, options[:controller]),
|
384
386
|
)
|
385
387
|
end
|
386
388
|
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_klass_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_klass_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
|
@@ -220,6 +224,8 @@ module ActionDispatch
|
|
220
224
|
relationship_name = relationship.first
|
221
225
|
relationship = source._relationships[relationship_name]
|
222
226
|
|
227
|
+
relationship._routed = true
|
228
|
+
|
223
229
|
formatted_relationship_name = format_route(relationship.name)
|
224
230
|
|
225
231
|
if relationship.polymorphic?
|
@@ -242,6 +248,8 @@ module ActionDispatch
|
|
242
248
|
relationship_name = relationship.first
|
243
249
|
relationship = source._relationships[relationship_name]
|
244
250
|
|
251
|
+
relationship._routed = true
|
252
|
+
|
245
253
|
formatted_relationship_name = format_route(relationship.name)
|
246
254
|
related_resource = JSONAPI::Resource.resource_klass_for(resource_type_with_module_prefix(relationship.class_name.underscore))
|
247
255
|
options[:controller] ||= related_resource._type.to_s
|
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.10.0.
|
4
|
+
version: 0.10.0.beta6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Gebhardt
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-07-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|