dulead-jsonapi-serializer 2.2.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.
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ ::ActiveRecord::Associations::Builder::HasOne.class_eval do
4
+ # Based on
5
+ # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/builder/collection_association.rb#L50
6
+ # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/builder/singular_association.rb#L11
7
+ def self.define_accessors(mixin, reflection)
8
+ super
9
+ name = reflection.name
10
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
11
+ def #{name}_id
12
+ # if an attribute is already defined with this methods name we should just use it
13
+ return read_attribute(__method__) if has_attribute?(__method__)
14
+ association(:#{name}).reader.try(:id)
15
+ end
16
+ CODE
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ require 'fast_jsonapi/scalar'
2
+
3
+ module FastJsonapi
4
+ class Attribute < Scalar; end
5
+ end
@@ -0,0 +1,21 @@
1
+ module FastJsonapi
2
+ class << self
3
+ # Calls either a Proc or a Lambda, making sure to never pass more parameters to it than it can receive
4
+ #
5
+ # @param [Proc] proc the Proc or Lambda to call
6
+ # @param [Array<Object>] *params any number of parameters to be passed to the Proc
7
+ # @return [Object] the result of the Proc call with the supplied parameters
8
+ def call_proc(proc, *params)
9
+ # The parameters array for a lambda created from a symbol (&:foo) differs
10
+ # from explictly defined procs/lambdas, so we can't deduce the number of
11
+ # parameters from the array length (and differs between Ruby 2.x and 3).
12
+ # In the case of negative arity -- unlimited/unknown argument count --
13
+ # just send the object to act as the method receiver.
14
+ if proc.arity.negative?
15
+ proc.call(params.first)
16
+ else
17
+ proc.call(*params.take(proc.parameters.length))
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ require 'skylight'
2
+
3
+ warn('DEPRECATION: Skylight support was moved into the `skylight` gem.')
@@ -0,0 +1,7 @@
1
+ require 'jsonapi/serializer/instrumentation'
2
+
3
+ warn(
4
+ 'DEPRECATION: Performance instrumentation is no longer automatic. See: ' \
5
+ 'https://github.com/jsonapi-serializer/jsonapi-serializer' \
6
+ '#performance-instrumentation'
7
+ )
@@ -0,0 +1,5 @@
1
+ require 'fast_jsonapi/scalar'
2
+
3
+ module FastJsonapi
4
+ class Link < Scalar; end
5
+ end
@@ -0,0 +1,357 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/time'
4
+ require 'active_support/concern'
5
+ require 'active_support/inflector'
6
+ require 'active_support/core_ext/numeric/time'
7
+ require 'fast_jsonapi/helpers'
8
+ require 'fast_jsonapi/attribute'
9
+ require 'fast_jsonapi/relationship'
10
+ require 'fast_jsonapi/link'
11
+ require 'fast_jsonapi/serialization_core'
12
+
13
+ module FastJsonapi
14
+ module ObjectSerializer
15
+ extend ActiveSupport::Concern
16
+ include SerializationCore
17
+
18
+ TRANSFORMS_MAPPING = {
19
+ camel: :camelize,
20
+ camel_lower: [:camelize, :lower],
21
+ dash: :dasherize,
22
+ underscore: :underscore
23
+ }.freeze
24
+
25
+ included do
26
+ # Set record_type based on the name of the serializer class
27
+ set_type(reflected_record_type) if reflected_record_type
28
+ end
29
+
30
+ def initialize(resource, options = {})
31
+ process_options(options)
32
+
33
+ @resource = resource
34
+ end
35
+
36
+ def serializable_hash
37
+ if self.class.is_collection?(@resource, @is_collection)
38
+ return hash_for_collection
39
+ end
40
+
41
+ hash_for_one_record
42
+ end
43
+ alias to_hash serializable_hash
44
+
45
+ def hash_for_one_record
46
+ serializable_hash = { data: nil }
47
+ serializable_hash[:meta] = @meta if @meta.present?
48
+ serializable_hash[:links] = @links if @links.present?
49
+
50
+ return serializable_hash unless @resource
51
+
52
+ serializable_hash[:data] = self.class.record_hash(@resource, @fieldsets[self.class.record_type.to_sym], @includes, @params)
53
+ serializable_hash[:included] = self.class.get_included_records(@resource, @includes, @known_included_objects, @fieldsets, @params) if @includes.present?
54
+ serializable_hash
55
+ end
56
+
57
+ def hash_for_collection
58
+ serializable_hash = {}
59
+
60
+ data = []
61
+ included = []
62
+ fieldset = @fieldsets[self.class.record_type.to_sym]
63
+ @resource.each do |record|
64
+ data << self.class.record_hash(record, fieldset, @includes, @params)
65
+ included.concat self.class.get_included_records(record, @includes, @known_included_objects, @fieldsets, @params) if @includes.present?
66
+ end
67
+
68
+ serializable_hash[:data] = data
69
+ serializable_hash[:included] = included if @includes.present?
70
+ serializable_hash[:meta] = @meta if @meta.present?
71
+ serializable_hash[:links] = @links if @links.present?
72
+ serializable_hash
73
+ end
74
+
75
+ private
76
+
77
+ def process_options(options)
78
+ @fieldsets = deep_symbolize(options[:fields].presence || {})
79
+ @params = {}
80
+
81
+ return if options.blank?
82
+
83
+ @known_included_objects = Set.new
84
+ @meta = options[:meta]
85
+ @links = options[:links]
86
+ @is_collection = options[:is_collection]
87
+ @params = options[:params] || {}
88
+ raise ArgumentError, '`params` option passed to serializer must be a hash' unless @params.is_a?(Hash)
89
+
90
+ if options[:include].present?
91
+ @includes = options[:include].reject(&:blank?).map(&:to_sym)
92
+ self.class.validate_includes!(@includes)
93
+ end
94
+ end
95
+
96
+ def deep_symbolize(collection)
97
+ if collection.is_a? Hash
98
+ collection.each_with_object({}) do |(k, v), hsh|
99
+ hsh[k.to_sym] = deep_symbolize(v)
100
+ end
101
+ elsif collection.is_a? Array
102
+ collection.map { |i| deep_symbolize(i) }
103
+ else
104
+ collection.to_sym
105
+ end
106
+ end
107
+
108
+ class_methods do
109
+ # Detects a collection/enumerable
110
+ #
111
+ # @return [TrueClass] on a successful detection
112
+ def is_collection?(resource, force_is_collection = nil)
113
+ return force_is_collection unless force_is_collection.nil?
114
+
115
+ resource.is_a?(Enumerable) && !resource.respond_to?(:each_pair)
116
+ end
117
+
118
+ def inherited(subclass)
119
+ super(subclass)
120
+ subclass.attributes_to_serialize = attributes_to_serialize.dup if attributes_to_serialize.present?
121
+ subclass.relationships_to_serialize = relationships_to_serialize.dup if relationships_to_serialize.present?
122
+ subclass.cachable_relationships_to_serialize = cachable_relationships_to_serialize.dup if cachable_relationships_to_serialize.present?
123
+ subclass.uncachable_relationships_to_serialize = uncachable_relationships_to_serialize.dup if uncachable_relationships_to_serialize.present?
124
+ subclass.transform_method = transform_method
125
+ subclass.data_links = data_links.dup if data_links.present?
126
+ subclass.cache_store_instance = cache_store_instance
127
+ subclass.cache_store_options = cache_store_options
128
+ subclass.set_type(subclass.reflected_record_type) if subclass.reflected_record_type
129
+ subclass.meta_to_serialize = meta_to_serialize
130
+ subclass.record_id = record_id
131
+ subclass.record_type_block = record_type_block
132
+ end
133
+
134
+ def reflected_record_type
135
+ return @reflected_record_type if defined?(@reflected_record_type)
136
+
137
+ @reflected_record_type ||= begin
138
+ name.split('::').last.chomp('Serializer').underscore.to_sym if name&.end_with?('Serializer')
139
+ end
140
+ end
141
+
142
+ def set_key_transform(transform_name)
143
+ self.transform_method = TRANSFORMS_MAPPING[transform_name.to_sym]
144
+
145
+ # ensure that the record type is correctly transformed
146
+ if record_type
147
+ set_type(record_type)
148
+ # TODO: Remove dead code
149
+ elsif reflected_record_type
150
+ set_type(reflected_record_type)
151
+ end
152
+ end
153
+
154
+ def run_key_transform(input)
155
+ if transform_method.present?
156
+ input.to_s.send(*@transform_method).to_sym
157
+ else
158
+ input.to_sym
159
+ end
160
+ end
161
+
162
+ def use_hyphen
163
+ warn('DEPRECATION WARNING: use_hyphen is deprecated and will be removed from fast_jsonapi 2.0 use (set_key_transform :dash) instead')
164
+ set_key_transform :dash
165
+ end
166
+
167
+ def set_type(type_name)
168
+ self.record_type = run_key_transform(type_name)
169
+ end
170
+
171
+ def set_id(id_name = nil, &block)
172
+ self.record_id = block || id_name
173
+ end
174
+
175
+ def set_record_type_block(&block)
176
+ self.record_type_block = block
177
+ end
178
+
179
+ def cache_options(cache_options)
180
+ # FIXME: remove this if block once deprecated cache_options are not supported anymore
181
+ unless cache_options.key?(:store)
182
+ # fall back to old, deprecated behaviour because no store was passed.
183
+ # we assume the user explicitly wants new behaviour if he passed a
184
+ # store because this is the new syntax.
185
+ deprecated_cache_options(cache_options)
186
+ return
187
+ end
188
+
189
+ self.cache_store_instance = cache_options[:store]
190
+ self.cache_store_options = cache_options.except(:store)
191
+ end
192
+
193
+ # FIXME: remove this method once deprecated cache_options are not supported anymore
194
+ def deprecated_cache_options(cache_options)
195
+ warn('DEPRECATION WARNING: `store:` is a required cache option, we will default to `Rails.cache` for now. See https://github.com/fast-jsonapi/fast_jsonapi#caching for more information.')
196
+
197
+ %i[enabled cache_length].select { |key| cache_options.key?(key) }.each do |key|
198
+ warn("DEPRECATION WARNING: `#{key}` is a deprecated cache option and will have no effect soon. See https://github.com/fast-jsonapi/fast_jsonapi#caching for more information.")
199
+ end
200
+
201
+ self.cache_store_instance = cache_options[:enabled] ? Rails.cache : nil
202
+ self.cache_store_options = {
203
+ expires_in: cache_options[:cache_length] || 5.minutes,
204
+ race_condition_ttl: cache_options[:race_condition_ttl] || 5.seconds
205
+ }
206
+ end
207
+
208
+ def attributes(*attributes_list, &block)
209
+ attributes_list = attributes_list.first if attributes_list.first.class.is_a?(Array)
210
+ options = attributes_list.last.is_a?(Hash) ? attributes_list.pop : {}
211
+ self.attributes_to_serialize = {} if attributes_to_serialize.nil?
212
+
213
+ # to support calling `attribute` with a lambda, e.g `attribute :key, ->(object) { ... }`
214
+ block = attributes_list.pop if attributes_list.last.is_a?(Proc)
215
+
216
+ attributes_list.each do |attr_name|
217
+ method_name = attr_name
218
+ key = run_key_transform(method_name)
219
+ attributes_to_serialize[key] = Attribute.new(
220
+ key: key,
221
+ method: block || method_name,
222
+ options: options
223
+ )
224
+ end
225
+ end
226
+
227
+ alias_method :attribute, :attributes
228
+
229
+ def add_relationship(relationship)
230
+ self.relationships_to_serialize = {} if relationships_to_serialize.nil?
231
+ self.cachable_relationships_to_serialize = {} if cachable_relationships_to_serialize.nil?
232
+ self.uncachable_relationships_to_serialize = {} if uncachable_relationships_to_serialize.nil?
233
+
234
+ # TODO: Remove this undocumented option.
235
+ # Delegate the caching to the serializer exclusively.
236
+ if relationship.cached
237
+ cachable_relationships_to_serialize[relationship.name] = relationship
238
+ else
239
+ uncachable_relationships_to_serialize[relationship.name] = relationship
240
+ end
241
+ relationships_to_serialize[relationship.name] = relationship
242
+ end
243
+
244
+ def has_many(relationship_name, options = {}, &block)
245
+ relationship = create_relationship(relationship_name, :has_many, options, block)
246
+ add_relationship(relationship)
247
+ end
248
+
249
+ def has_one(relationship_name, options = {}, &block)
250
+ relationship = create_relationship(relationship_name, :has_one, options, block)
251
+ add_relationship(relationship)
252
+ end
253
+
254
+ def belongs_to(relationship_name, options = {}, &block)
255
+ relationship = create_relationship(relationship_name, :belongs_to, options, block)
256
+ add_relationship(relationship)
257
+ end
258
+
259
+ def meta(meta_name = nil, &block)
260
+ self.meta_to_serialize = block || meta_name
261
+ end
262
+
263
+ def create_relationship(base_key, relationship_type, options, block)
264
+ name = base_key.to_sym
265
+ if relationship_type == :has_many
266
+ base_serialization_key = base_key.to_s.singularize
267
+ id_postfix = '_ids'
268
+ else
269
+ base_serialization_key = base_key
270
+ id_postfix = '_id'
271
+ end
272
+ polymorphic = fetch_polymorphic_option(options)
273
+
274
+ Relationship.new(
275
+ owner: self,
276
+ key: options[:key] || run_key_transform(base_key),
277
+ name: name,
278
+ id_method_name: compute_id_method_name(
279
+ options[:id_method_name],
280
+ "#{base_serialization_key}#{id_postfix}".to_sym,
281
+ polymorphic,
282
+ options[:serializer],
283
+ block
284
+ ),
285
+ record_type: options[:record_type],
286
+ object_method_name: options[:object_method_name] || name,
287
+ object_block: block,
288
+ serializer: options[:serializer],
289
+ relationship_type: relationship_type,
290
+ cached: options[:cached],
291
+ polymorphic: polymorphic,
292
+ conditional_proc: options[:if],
293
+ transform_method: @transform_method,
294
+ meta: options[:meta],
295
+ links: options[:links],
296
+ lazy_load_data: options[:lazy_load_data]
297
+ )
298
+ end
299
+
300
+ def compute_id_method_name(custom_id_method_name, id_method_name_from_relationship, polymorphic, serializer, block)
301
+ if block.present? || serializer.is_a?(Proc) || polymorphic
302
+ custom_id_method_name || :id
303
+ else
304
+ custom_id_method_name || id_method_name_from_relationship
305
+ end
306
+ end
307
+
308
+ def serializer_for(name)
309
+ namespace = self.name.gsub(/()?\w+Serializer$/, '')
310
+ serializer_name = "#{name.to_s.demodulize.classify}Serializer"
311
+ serializer_class_name = namespace + serializer_name
312
+ begin
313
+ serializer_class_name.constantize
314
+ rescue NameError
315
+ raise NameError, "#{self.name} cannot resolve a serializer class for '#{name}'. " \
316
+ "Attempted to find '#{serializer_class_name}'. " \
317
+ 'Consider specifying the serializer directly through options[:serializer].'
318
+ end
319
+ end
320
+
321
+ def fetch_polymorphic_option(options)
322
+ option = options[:polymorphic]
323
+ return false unless option.present?
324
+ return option if option.respond_to? :keys
325
+
326
+ {}
327
+ end
328
+
329
+ # def link(link_name, link_method_name = nil, &block)
330
+ def link(*params, &block)
331
+ self.data_links = {} if data_links.nil?
332
+
333
+ options = params.last.is_a?(Hash) ? params.pop : {}
334
+ link_name = params.first
335
+ link_method_name = params[-1]
336
+ key = run_key_transform(link_name)
337
+
338
+ data_links[key] = Link.new(
339
+ key: key,
340
+ method: block || link_method_name,
341
+ options: options
342
+ )
343
+ end
344
+
345
+ def validate_includes!(includes)
346
+ return if includes.blank?
347
+
348
+ parse_includes_list(includes).each_key do |include_item|
349
+ relationship_to_include = relationships_to_serialize[include_item]
350
+ raise(JSONAPI::Serializer::UnsupportedIncludeError.new(include_item, name)) unless relationship_to_include
351
+
352
+ relationship_to_include.static_serializer # called for a side-effect to check for a known serializer class.
353
+ end
354
+ end
355
+ end
356
+ end
357
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/railtie'
4
+
5
+ class Railtie < Rails::Railtie
6
+ initializer 'fast_jsonapi.active_record' do
7
+ ActiveSupport.on_load :active_record do
8
+ require 'extensions/has_one'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,236 @@
1
+ module FastJsonapi
2
+ class Relationship
3
+ attr_reader :owner, :key, :name, :id_method_name, :record_type, :object_method_name, :object_block, :serializer, :relationship_type, :cached, :polymorphic, :conditional_proc, :transform_method, :links, :meta, :lazy_load_data
4
+
5
+ def initialize(
6
+ owner:,
7
+ key:,
8
+ name:,
9
+ id_method_name:,
10
+ record_type:,
11
+ object_method_name:,
12
+ object_block:,
13
+ serializer:,
14
+ relationship_type:,
15
+ polymorphic:,
16
+ conditional_proc:,
17
+ transform_method:,
18
+ links:,
19
+ meta:,
20
+ cached: false,
21
+ lazy_load_data: false
22
+ )
23
+ @owner = owner
24
+ @key = key
25
+ @name = name
26
+ @id_method_name = id_method_name
27
+ @record_type = record_type
28
+ @object_method_name = object_method_name
29
+ @object_block = object_block
30
+ @serializer = serializer
31
+ @relationship_type = relationship_type
32
+ @cached = cached
33
+ @polymorphic = polymorphic
34
+ @conditional_proc = conditional_proc
35
+ @transform_method = transform_method
36
+ @links = links || {}
37
+ @meta = meta || {}
38
+ @lazy_load_data = lazy_load_data
39
+ @record_types_for = {}
40
+ @serializers_for_name = {}
41
+ end
42
+
43
+ def serialize(record, included, serialization_params, output_hash)
44
+ if include_relationship?(record, serialization_params)
45
+ empty_case = relationship_type == :has_many ? [] : nil
46
+
47
+ output_hash[key] = {}
48
+ output_hash[key][:data] = ids_hash_from_record_and_relationship(record, serialization_params) || empty_case unless lazy_load_data && !included
49
+
50
+ add_meta_hash(record, serialization_params, output_hash) if meta.present?
51
+ add_links_hash(record, serialization_params, output_hash) if links.present?
52
+ end
53
+ end
54
+
55
+ def fetch_associated_object(record, params)
56
+ return FastJsonapi.call_proc(object_block, record, params) unless object_block.nil?
57
+
58
+ record.send(object_method_name)
59
+ end
60
+
61
+ def include_relationship?(record, serialization_params)
62
+ if conditional_proc.present?
63
+ FastJsonapi.call_proc(conditional_proc, record, serialization_params)
64
+ else
65
+ true
66
+ end
67
+ end
68
+
69
+ def serializer_for(record, serialization_params)
70
+ # TODO: Remove this, dead code...
71
+ if @static_serializer
72
+ @static_serializer
73
+
74
+ elsif polymorphic
75
+ name = polymorphic[record.class] if polymorphic.is_a?(Hash)
76
+ name ||= record.class.name
77
+ serializer_for_name(name)
78
+
79
+ elsif serializer.is_a?(Proc)
80
+ FastJsonapi.call_proc(serializer, record, serialization_params)
81
+
82
+ elsif object_block
83
+ serializer_for_name(record.class.name)
84
+
85
+ else
86
+ # TODO: Remove this, dead code...
87
+ raise "Unknown serializer for object #{record.inspect}"
88
+ end
89
+ end
90
+
91
+ def static_serializer
92
+ initialize_static_serializer unless @initialized_static_serializer
93
+ @static_serializer
94
+ end
95
+
96
+ def static_record_type
97
+ initialize_static_serializer unless @initialized_static_serializer
98
+ @static_record_type
99
+ end
100
+
101
+ private
102
+
103
+ def ids_hash_from_record_and_relationship(record, params = {})
104
+ initialize_static_serializer unless @initialized_static_serializer
105
+
106
+ return ids_hash(fetch_id(record, params), @static_record_type) if @static_record_type
107
+
108
+ return unless associated_object = fetch_associated_object(record, params)
109
+
110
+ if associated_object.respond_to? :map
111
+ return associated_object.map do |object|
112
+ id_hash_from_record object, params
113
+ end
114
+ end
115
+
116
+ id_hash_from_record associated_object, params
117
+ end
118
+
119
+ def id_hash_from_record(record, params)
120
+ associated_record_type = record_type_for(record, params)
121
+ id_hash(record.public_send(id_method_name), associated_record_type)
122
+ end
123
+
124
+ def ids_hash(ids, record_type)
125
+ return ids.map { |id| id_hash(id, record_type) } if ids.respond_to? :map
126
+
127
+ id_hash(ids, record_type) # ids variable is just a single id here
128
+ end
129
+
130
+ def id_hash(id, record_type, default_return = false)
131
+ if id.present?
132
+ { id: id.to_s, type: record_type }
133
+ else
134
+ default_return ? { id: nil, type: record_type } : nil
135
+ end
136
+ end
137
+
138
+ def fetch_id(record, params)
139
+ if object_block.present?
140
+ object = FastJsonapi.call_proc(object_block, record, params)
141
+ return object.map { |item| item.public_send(id_method_name) } if object.respond_to? :map
142
+
143
+ return object.try(id_method_name)
144
+ end
145
+ record.public_send(id_method_name)
146
+ end
147
+
148
+ def add_links_hash(record, params, output_hash)
149
+ output_hash[key][:links] = if links.is_a?(Symbol)
150
+ record.public_send(links)
151
+ else
152
+ links.each_with_object({}) do |(key, method), hash|
153
+ Link.new(key: key, method: method).serialize(record, params, hash)
154
+ end
155
+ end
156
+ end
157
+
158
+ def add_meta_hash(record, params, output_hash)
159
+ output_hash[key][:meta] = if meta.is_a?(Proc)
160
+ FastJsonapi.call_proc(meta, record, params)
161
+ else
162
+ meta
163
+ end
164
+ end
165
+
166
+ def run_key_transform(input)
167
+ if transform_method.present?
168
+ input.to_s.send(*transform_method).to_sym
169
+ else
170
+ input.to_sym
171
+ end
172
+ end
173
+
174
+ def initialize_static_serializer
175
+ return if @initialized_static_serializer
176
+
177
+ @static_serializer = compute_static_serializer
178
+ @static_record_type = compute_static_record_type
179
+ @initialized_static_serializer = true
180
+ end
181
+
182
+ def compute_static_serializer
183
+ if polymorphic
184
+ # polymorphic without a specific serializer --
185
+ # the serializer is determined on a record-by-record basis
186
+ nil
187
+
188
+ elsif serializer.is_a?(Symbol) || serializer.is_a?(String)
189
+ # a serializer was explicitly specified by name -- determine the serializer class
190
+ serializer_for_name(serializer)
191
+
192
+ elsif serializer.is_a?(Proc)
193
+ # the serializer is a Proc to be executed per object -- not static
194
+ nil
195
+
196
+ elsif serializer
197
+ # something else was specified, e.g. a specific serializer class -- return it
198
+ serializer
199
+
200
+ elsif object_block
201
+ # an object block is specified without a specific serializer --
202
+ # assume the objects might be different and infer the serializer by their class
203
+ nil
204
+
205
+ else
206
+ # no serializer information was provided -- infer it from the relationship name
207
+ serializer_name = name.to_s
208
+ serializer_name = serializer_name.singularize if relationship_type.to_sym == :has_many
209
+ serializer_for_name(serializer_name)
210
+ end
211
+ end
212
+
213
+ def serializer_for_name(name)
214
+ @serializers_for_name[name] ||= owner.serializer_for(name)
215
+ end
216
+
217
+ def record_type_for(record, serialization_params)
218
+ # if the record type is static, return it
219
+ return @static_record_type if @static_record_type
220
+
221
+ # if not, use the record type of the serializer, and memoize the transformed version
222
+ serializer = serializer_for(record, serialization_params)
223
+ @record_types_for[serializer] ||= run_key_transform(serializer.record_type)
224
+ end
225
+
226
+ def compute_static_record_type
227
+ if polymorphic
228
+ nil
229
+ elsif record_type
230
+ run_key_transform(record_type)
231
+ elsif @static_serializer
232
+ run_key_transform(@static_serializer.record_type)
233
+ end
234
+ end
235
+ end
236
+ end