rest_framework 0.9.16 → 0.10.0

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: 59084182eeedcec7d3f1a1a913a99e55a6139bb394e4c712744c5d80778db800
4
- data.tar.gz: 552ea8a39833dc6a3ec4c689f120ba549af0db49a3fafa29d63cd4cb17d85a85
3
+ metadata.gz: 8a916afbf32cf43553b8aa952024011639f311ab80db53685163e607e48e1ad0
4
+ data.tar.gz: 1cc8aa7aed712a63b1ef9586c37b64a87de62fe5dfdcf659e982a1b77c20fd89
5
5
  SHA512:
6
- metadata.gz: cffd1cde2cbf956d46344018c137b723397118f3aa4ea16c2d9abf5c9d9694c8a78d8f706f96e28c637ec4f58d692553da372a832a0bd44cc58154134b733d33
7
- data.tar.gz: 1eea97e45fc0f4c47edbdb04a8de05fe6e383e259ea1d3ff48196b6601aeb87341aa6750f8eb4411dd0e16934452c5a02b2d26877a9ec8382ae538312f305603
6
+ metadata.gz: bef1f7c3c52c7a42e8c307ccaf37e4e25f4e663359e26be433f20fd644fca0e59cd3b56613f965b084662046577576728981a320d1d5a5a6517d98556008fc99
7
+ data.tar.gz: '080f96e20b330a391b896db89a192e415328aa320f8d669260d8d282c0eee709022afa7fa5dd484449eb5bba85544f8974d24764a5e5b45821803d1ccd3c23f0'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.16
1
+ 0.10.0
@@ -17,6 +17,10 @@ module RESTFramework::Mixins::BaseControllerMixin
17
17
  serializer_class: nil,
18
18
  serialize_to_json: true,
19
19
  serialize_to_xml: true,
20
+
21
+ # Custom integrations (reduces serializer performance due to method calls).
22
+ enable_action_text: false,
23
+ enable_active_storage: false,
20
24
  }
21
25
  RRF_BASE_INSTANCE_CONFIG = {
22
26
  # Options related to pagination.
@@ -103,13 +103,20 @@ module RESTFramework::Mixins::BaseModelControllerMixin
103
103
  # If fields is a hash, then parse it.
104
104
  if input_fields.is_a?(Hash)
105
105
  return RESTFramework::Utils.parse_fields_hash(
106
- input_fields, self.get_model, exclude_associations: self.exclude_associations
106
+ input_fields,
107
+ self.get_model,
108
+ exclude_associations: self.exclude_associations,
109
+ action_text: self.enable_action_text,
110
+ active_storage: self.enable_active_storage,
107
111
  )
108
112
  elsif !input_fields
109
113
  # Otherwise, if fields is nil, then fallback to columns.
110
114
  model = self.get_model
111
115
  return model ? RESTFramework::Utils.fields_for(
112
- model, exclude_associations: self.exclude_associations
116
+ model,
117
+ exclude_associations: self.exclude_associations,
118
+ action_text: self.enable_action_text,
119
+ active_storage: self.enable_active_storage,
113
120
  ) : []
114
121
  elsif input_fields
115
122
  input_fields = input_fields.map(&:to_s)
@@ -418,21 +425,21 @@ module RESTFramework::Mixins::BaseModelControllerMixin
418
425
  @_get_allowed_parameters = self.get_fields.map { |f|
419
426
  f = f.to_s
420
427
 
421
- # ActiveStorage Integration: `has_one_attached`.
422
- if reflections.key?("#{f}_attachment")
423
- hash_variations[f] = ACTIVESTORAGE_KEYS
428
+ # ActionText Integration:
429
+ if self.class.enable_action_text && reflections.key?("rich_test_#{f}")
424
430
  next f
425
431
  end
426
432
 
427
- # ActiveStorage Integration: `has_many_attached`.
428
- if reflections.key?("#{f}_attachments")
433
+ # ActiveStorage Integration: `has_one_attached`
434
+ if self.class.enable_active_storage && reflections.key?("#{f}_attachment")
429
435
  hash_variations[f] = ACTIVESTORAGE_KEYS
430
- next nil
436
+ next f
431
437
  end
432
438
 
433
- # ActionText Integration.
434
- if reflections.key?("rich_test_#{f}")
435
- next f
439
+ # ActiveStorage Integration: `has_many_attached`
440
+ if self.class.enable_active_storage && reflections.key?("#{f}_attachments")
441
+ hash_variations[f] = ACTIVESTORAGE_KEYS
442
+ next nil
436
443
  end
437
444
 
438
445
  # Return field if it's not an association.
@@ -513,31 +520,33 @@ module RESTFramework::Mixins::BaseModelControllerMixin
513
520
  #
514
521
  # rubocop:enable Layout/LineLength
515
522
  has_many_attached_scalar_data = {}
516
- self.class.get_model.attachment_reflections.keys.each do |k|
517
- if data[k].is_a?(Array)
518
- data[k] = data[k].map { |v|
519
- if v.is_a?(String)
520
- v = BASE64_TRANSLATE.call(k, v)
521
-
522
- # Remember scalars because Rails strong params will remove it.
523
+ if self.class.enable_active_storage
524
+ self.class.get_model.attachment_reflections.keys.each do |k|
525
+ if data[k].is_a?(Array)
526
+ data[k] = data[k].map { |v|
523
527
  if v.is_a?(String)
524
- has_many_attached_scalar_data[k] ||= []
525
- has_many_attached_scalar_data[k] << v
526
- end
527
- elsif v.is_a?(Hash)
528
- if v[:io].is_a?(String)
529
- v[:io] = StringIO.new(Base64.decode64(v[:io]))
528
+ v = BASE64_TRANSLATE.call(k, v)
529
+
530
+ # Remember scalars because Rails strong params will remove it.
531
+ if v.is_a?(String)
532
+ has_many_attached_scalar_data[k] ||= []
533
+ has_many_attached_scalar_data[k] << v
534
+ end
535
+ elsif v.is_a?(Hash)
536
+ if v[:io].is_a?(String)
537
+ v[:io] = StringIO.new(Base64.decode64(v[:io]))
538
+ end
530
539
  end
531
- end
532
540
 
533
- next v
534
- }
535
- elsif data[k].is_a?(Hash)
536
- if data[k][:io].is_a?(String)
537
- data[k][:io] = StringIO.new(Base64.decode64(data[k][:io]))
541
+ next v
542
+ }
543
+ elsif data[k].is_a?(Hash)
544
+ if data[k][:io].is_a?(String)
545
+ data[k][:io] = StringIO.new(Base64.decode64(data[k][:io]))
546
+ end
547
+ elsif data[k].is_a?(String)
548
+ data[k] = BASE64_TRANSLATE.call(k, data[k])
538
549
  end
539
- elsif data[k].is_a?(String)
540
- data[k] = BASE64_TRANSLATE.call(k, data[k])
541
550
  end
542
551
  end
543
552
 
@@ -246,28 +246,38 @@ class RESTFramework::Serializers::NativeSerializer < RESTFramework::Serializers:
246
246
  includes[f] = sub_config
247
247
  includes_map[f] = f.to_sym
248
248
  end
249
- elsif ref = reflections["rich_text_#{f}"]
249
+ elsif @controller.class.enable_action_text && ref = reflections["rich_text_#{f}"]
250
250
  # ActionText Integration: Define rich text serializer method.
251
251
  includes_map[f] = :"rich_text_#{f}"
252
252
  serializer_methods[f] = f
253
253
  self.define_singleton_method(f) do |record|
254
254
  next record.send(f).to_s
255
255
  end
256
- elsif ref = attachment_reflections[f]
256
+ elsif @controller.class.enable_active_storage && ref = attachment_reflections[f]
257
257
  # ActiveStorage Integration: Define attachment serializer method.
258
258
  if ref.macro == :has_one_attached
259
259
  serializer_methods[f] = f
260
260
  includes_map[f] = {"#{f}_attachment": :blob}
261
261
  self.define_singleton_method(f) do |record|
262
262
  attached = record.send(f)
263
- next attached.attachment ? {signed_id: attached.signed_id, url: attached.url} : nil
263
+ next attached.attachment ? {
264
+ filename: attached.filename,
265
+ signed_id: attached.signed_id,
266
+ url: attached.url,
267
+ } : nil
264
268
  end
265
269
  elsif ref.macro == :has_many_attached
266
270
  serializer_methods[f] = f
267
271
  includes_map[f] = {"#{f}_attachments": :blob}
268
272
  self.define_singleton_method(f) do |record|
269
273
  # Iterating the collection yields attachment objects.
270
- next record.send(f).map { |a| {signed_id: a.signed_id, url: a.url} }
274
+ next record.send(f).map { |a|
275
+ {
276
+ filename: a.filename,
277
+ signed_id: a.signed_id,
278
+ url: a.url,
279
+ }
280
+ }
271
281
  end
272
282
  end
273
283
  elsif @model.method_defined?(f)
@@ -153,16 +153,21 @@ module RESTFramework::Utils
153
153
  end
154
154
 
155
155
  # Parse fields hashes.
156
- def self.parse_fields_hash(fields_hash, model, exclude_associations: nil)
157
- parsed_fields = fields_hash[:only] || (
158
- model ? self.fields_for(model, exclude_associations: exclude_associations) : []
156
+ def self.parse_fields_hash(h, model, exclude_associations:, action_text:, active_storage:)
157
+ parsed_fields = h[:only] || (
158
+ model ? self.fields_for(
159
+ model,
160
+ exclude_associations: exclude_associations,
161
+ action_text: action_text,
162
+ active_storage: active_storage,
163
+ ) : []
159
164
  )
160
- parsed_fields += fields_hash[:include].map(&:to_s) if fields_hash[:include]
161
- parsed_fields -= fields_hash[:exclude].map(&:to_s) if fields_hash[:exclude]
162
- parsed_fields -= fields_hash[:except].map(&:to_s) if fields_hash[:except]
165
+ parsed_fields += h[:include].map(&:to_s) if h[:include]
166
+ parsed_fields -= h[:exclude].map(&:to_s) if h[:exclude]
167
+ parsed_fields -= h[:except].map(&:to_s) if h[:except]
163
168
 
164
169
  # Warn for any unknown keys.
165
- (fields_hash.keys - [:only, :except, :include, :exclude]).each do |k|
170
+ (h.keys - [:only, :except, :include, :exclude]).each do |k|
166
171
  Rails.logger.warn("RRF: Unknown key in fields hash: #{k}")
167
172
  end
168
173
 
@@ -173,16 +178,24 @@ module RESTFramework::Utils
173
178
  # Get the fields for a given model, including not just columns (which includes
174
179
  # foreign keys), but also associations. Note that we always return an array of
175
180
  # strings, not symbols.
176
- def self.fields_for(model, exclude_associations: nil)
181
+ def self.fields_for(model, exclude_associations:, action_text:, active_storage:)
177
182
  foreign_keys = model.reflect_on_all_associations(:belongs_to).map(&:foreign_key)
178
183
  base_fields = model.column_names.reject { |c| c.in?(foreign_keys) }
179
184
 
180
185
  return base_fields if exclude_associations
181
186
 
182
- # Add associations in addition to normal columns.
183
- return base_fields + model.reflections.map { |association, ref|
187
+ # ActionText Integration: Determine the normalized field names for action text attributes.
188
+ atf = action_text ? model.reflect_on_all_associations(:has_one).collect(&:name).select { |n|
189
+ n.to_s.start_with?("rich_text_")
190
+ }.map { |n| n.to_s.delete_prefix("rich_text_") } : []
191
+
192
+ # ActiveStorage Integration: Determine the normalized field names for active storage attributes.
193
+ asf = active_storage ? model.attachment_reflections.keys : []
194
+
195
+ # Associations:
196
+ associations = model.reflections.map { |association, ref|
184
197
  # Ignore associations for which we have custom integrations.
185
- if ref.class_name.in?(%w(ActiveStorage::Attachment ActiveStorage::Blob ActionText::RichText))
198
+ if ref.class_name.in?(%w(ActionText::RichText ActiveStorage::Attachment ActiveStorage::Blob))
186
199
  next nil
187
200
  end
188
201
 
@@ -193,11 +206,9 @@ module RESTFramework::Utils
193
206
  end
194
207
 
195
208
  next association
196
- }.compact + model.reflect_on_all_associations(:has_one).collect(&:name).select { |n|
197
- n.to_s.start_with?("rich_text_")
198
- }.map { |n|
199
- n.to_s.delete_prefix("rich_text_")
200
- } + model.attachment_reflections.keys
209
+ }.compact
210
+
211
+ return base_fields + associations + atf + asf
201
212
  end
202
213
 
203
214
  # Get the sub-fields that may be serialized and filtered/ordered for a reflection.
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.9.16
4
+ version: 0.10.0
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: 2024-12-21 00:00:00.000000000 Z
11
+ date: 2024-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails