rest_framework 0.5.5 → 0.5.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 237449a323a14356f20e47cd2cbab3591aa749fc7e6f43bc06587995ff1041dc
4
- data.tar.gz: 98ff07d840fca2fd09ab608a08a2814c5fe17c9ded1a7476c176941224c75e53
3
+ metadata.gz: a4a0533297190fd34ec007578f495d67ef19e3e02b7b495b8be004dd2180f6b2
4
+ data.tar.gz: 07f5478177e47bae6476c42587b10b698a862bbcfa762497a7bd11ebb5cf324e
5
5
  SHA512:
6
- metadata.gz: 5219df61d409aeda527a61508694cf5b46dba856f03db4d7a2432d8d208a89eb5ccaccee2d7da88472d5b2735a77b235127d903497b9bb3fb19b740f2eb5df05
7
- data.tar.gz: afbc3a40c39d312a0ebaaade7ce8c1d4d00b99fbd3da4168b0e9706d63d2fb59aa6d0f1d56cc4832a6eca10b783f43c20a2f9cf8d1015ef817293ba5852a7a62
6
+ metadata.gz: d971192a3c797b69e9e7982f2f7e381b7fa2784db39e592c56f3640683985424e40a52e28a0ff503f0c22ad2b0cedbd828ba5b4461e354abe36d5d9e8c01c370
7
+ data.tar.gz: 22f0d3779328a0c5dccb382674d44dfea4a5cffea92b96614366d9cbfa570ce436ea5774c13a16f524b995c54074d5ad5d979e82d081d2f012f89923f55339f6
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.5
1
+ 0.5.6
@@ -1,24 +1,39 @@
1
1
  # The base serializer defines the interface for all REST Framework serializers.
2
2
  class RESTFramework::BaseSerializer
3
+ # Add `object` accessor to be compatible with `ActiveModel::Serializer`.
3
4
  attr_accessor :object
4
5
 
5
- def initialize(object=nil, controller: nil, **kwargs)
6
+ # Accept/ignore `*args` to be compatible with the `ActiveModel::Serializer#initialize` signature.
7
+ def initialize(object=nil, *args, controller: nil, **kwargs)
6
8
  @object = object
7
9
  @controller = controller
8
10
  end
9
11
 
10
12
  # The primary interface for extracting a native Ruby types. This works both for records and
11
- # collections.
12
- def serialize(**kwargs)
13
+ # collections. We accept and ignore `*args` for compatibility with `active_model_serializers`.
14
+ def serialize(*args)
13
15
  raise NotImplementedError
14
16
  end
15
17
 
16
- # :nocov:
17
- # Synonym for `serializable_hash` or compatibility with ActiveModelSerializers.
18
- def serializable_hash(**kwargs)
19
- return self.serialize(**kwargs)
18
+ # Synonym for `serialize` for compatibility with `active_model_serializers`.
19
+ def serializable_hash(*args)
20
+ return self.serialize(*args)
21
+ end
22
+
23
+ # For compatibility with `active_model_serializers`.
24
+ def self.cache_enabled?
25
+ return false
26
+ end
27
+
28
+ # For compatibility with `active_model_serializers`.
29
+ def self.fragment_cache_enabled?
30
+ return false
31
+ end
32
+
33
+ # For compatibility with `active_model_serializers`.
34
+ def associations(*args, **kwargs)
35
+ return []
20
36
  end
21
- # :nocov:
22
37
  end
23
38
 
24
39
  # This serializer uses `.serializable_hash` to convert objects to Ruby primitives (with the
@@ -29,8 +44,9 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
29
44
  class_attribute :plural_config
30
45
  class_attribute :action_config
31
46
 
32
- def initialize(object=nil, many: nil, model: nil, **kwargs)
33
- super(object, **kwargs)
47
+ # Accept/ignore `*args` to be compatible with the `ActiveModel::Serializer#initialize` signature.
48
+ def initialize(object=nil, *args, many: nil, model: nil, **kwargs)
49
+ super(object, *args, **kwargs)
34
50
 
35
51
  if many.nil?
36
52
  # Determine if we are dealing with many objects or just one.
@@ -148,10 +164,7 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
148
164
  except = except.split(",").map(&:strip).map(&:to_sym)
149
165
 
150
166
  unless except.empty?
151
- # Duplicate the cfg to avoid mutating class state.
152
- cfg = cfg.deep_dup
153
-
154
- # Filter `only`, `except` (additive), `include`, and `methods`.
167
+ # Filter `only`, `except` (additive), `include`, `methods`, and `serializer_methods`.
155
168
  if cfg[:only]
156
169
  cfg[:only] = self.class.filter_subcfg(cfg[:only], except: except)
157
170
  else
@@ -159,14 +172,14 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
159
172
  end
160
173
  cfg[:include] = self.class.filter_subcfg(cfg[:include], except: except)
161
174
  cfg[:methods] = self.class.filter_subcfg(cfg[:methods], except: except)
175
+ cfg[:serializer_methods] = self.class.filter_subcfg(
176
+ cfg[:serializer_methods], except: except
177
+ )
162
178
  end
163
179
  elsif only_param && only = @controller.request.query_parameters[only_param].presence
164
180
  only = only.split(",").map(&:strip).map(&:to_sym)
165
181
 
166
182
  unless only.empty?
167
- # Duplicate the cfg to avoid mutating class state.
168
- cfg = cfg.deep_dup
169
-
170
183
  # For the `except` part of the serializer, we need to append any columns not in `only`.
171
184
  model = @controller.get_model
172
185
  except_cols = model&.column_names&.map(&:to_sym)&.reject { |c| c.in?(only) }
@@ -179,27 +192,31 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
179
192
  end
180
193
  cfg[:include] = self.class.filter_subcfg(cfg[:include], only: only)
181
194
  cfg[:methods] = self.class.filter_subcfg(cfg[:methods], only: only)
195
+ cfg[:serializer_methods] = self.class.filter_subcfg(cfg[:serializer_methods], only: only)
182
196
  end
183
197
  end
184
198
 
185
199
  return cfg
186
200
  end
187
201
 
188
- # Get the raw serializer config.
202
+ # Get the raw serializer config. Use `deep_dup` on any class mutables (array, hash, etc) to avoid
203
+ # mutating class state.
189
204
  def _get_raw_serializer_config
190
205
  # Return a locally defined serializer config if one is defined.
191
206
  if local_config = self.get_local_native_serializer_config
192
- return local_config
207
+ return local_config.deep_dup
193
208
  end
194
209
 
195
210
  # Return a serializer config if one is defined on the controller.
196
211
  if serializer_config = self.get_controller_native_serializer_config
197
- return serializer_config
212
+ return serializer_config.deep_dup
198
213
  end
199
214
 
200
215
  # If the config wasn't determined, build a serializer config from model fields.
201
216
  fields = @controller.get_fields if @controller
202
217
  if fields
218
+ fields = fields.deep_dup
219
+
203
220
  if @model
204
221
  columns, methods = fields.partition { |f| f.in?(@model.column_names) }
205
222
  else
@@ -216,15 +233,31 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
216
233
 
217
234
  # Get a configuration passable to `serializable_hash` for the object, filtered if required.
218
235
  def get_serializer_config
219
- return @_serializer_config ||= filter_except(self._get_raw_serializer_config)
236
+ return filter_except(self._get_raw_serializer_config)
237
+ end
238
+
239
+ # Internal helper to serialize a single record and merge results of `serializer_methods`.
240
+ def _serialize(record, config, serializer_methods)
241
+ # Ensure serializer_methods is either falsy, or an array.
242
+ if serializer_methods && !serializer_methods.respond_to?(:to_ary)
243
+ serializer_methods = [serializer_methods]
244
+ end
245
+
246
+ # Merge serialized record with any serializer method results.
247
+ return record.serializable_hash(config).merge(
248
+ serializer_methods&.map { |m| [m.to_sym, self.send(m, record)] }.to_h,
249
+ )
220
250
  end
221
251
 
222
- def serialize(**kwargs)
252
+ def serialize(*args)
253
+ config = self.get_serializer_config
254
+ serializer_methods = config.delete(:serializer_methods)
255
+
223
256
  if @object.respond_to?(:to_ary)
224
- return @object.map { |r| r.serializable_hash(self.get_serializer_config) }
257
+ return @object.map { |r| self._serialize(r, config, serializer_methods) }
225
258
  end
226
259
 
227
- return @object.serializable_hash(self.get_serializer_config)
260
+ return self._serialize(@object, config, serializer_methods)
228
261
  end
229
262
 
230
263
  # Allow a serializer instance to be used as a hash directly in a nested serializer config.
@@ -49,7 +49,7 @@ module RESTFramework::Utils
49
49
 
50
50
  # Helper to normalize a path pattern by replacing URL params with generic placeholder, and
51
51
  # removing the `(.:format)` at the end.
52
- def self.normalize_path(path)
52
+ def self.comparable_path(path)
53
53
  return path.gsub("(.:format)", "").gsub(/:[0-9A-Za-z_-]+/, ":x")
54
54
  end
55
55
 
@@ -58,7 +58,7 @@ module RESTFramework::Utils
58
58
  current_route ||= self.get_request_route(application_routes, request)
59
59
  current_path = current_route.path.spec.to_s
60
60
  current_levels = current_path.count("/")
61
- current_normalized_path = self.normalize_path(current_path)
61
+ current_comparable_path = self.comparable_path(current_path)
62
62
 
63
63
  # Return routes that match our current route subdomain/pattern, grouped by controller. We
64
64
  # precompute certain properties of the route for performance.
@@ -77,8 +77,9 @@ module RESTFramework::Utils
77
77
  route: r,
78
78
  verb: r.verb,
79
79
  path: path,
80
- normalized_path: self.normalize_path(path),
81
- relative_path: path.split("/")[current_levels..]&.join("/"),
80
+ comparable_path: self.comparable_path(path),
81
+ # Starts at the number of levels in current path, and removes the `(.:format)` at the end.
82
+ relative_path: path.split("/")[current_levels..]&.join("/")&.gsub("(.:format)", ""),
82
83
  controller: r.defaults[:controller].presence,
83
84
  action: r.defaults[:action].presence,
84
85
  subdomain: r.defaults[:subdomain].presence,
@@ -88,7 +89,7 @@ module RESTFramework::Utils
88
89
  }.select { |r|
89
90
  (
90
91
  (!r[:subdomain] || r[:subdomain] == request.subdomain.presence) &&
91
- r[:normalized_path].start_with?(current_normalized_path) &&
92
+ r[:comparable_path].start_with?(current_comparable_path) &&
92
93
  r[:controller] &&
93
94
  r[:action]
94
95
  )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest_framework
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 0.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregory N. Schmit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-15 00:00:00.000000000 Z
11
+ date: 2022-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails