@@ -9,10 +9,10 @@ module Caching
9
9
included do
10
10
with_options instance_writer : false , instance_reader : false do |serializer |
11
11
serializer . class_attribute :_cache # @api private : the cache store
12
- serializer . class_attribute :_fragmented # @api private : @see ::fragmented
12
+ serializer . class_attribute :_fragmented # @api private : Used ONLY by FragmentedSerializer to reference original serializer
13
13
serializer . class_attribute :_cache_key # @api private : when present, is first item in cache_key. Ignored if the serializable object defines #cache_key.
14
- serializer . class_attribute :_cache_only # @api private : when fragment caching, whitelists cached_attributes . Cannot combine with except
15
- serializer . class_attribute :_cache_except # @api private : when fragment caching, blacklists cached_attributes . Cannot combine with only
14
+ serializer . class_attribute :_cache_only # @api private : when fragment caching, whitelists fetch_attributes . Cannot combine with except
15
+ serializer . class_attribute :_cache_except # @api private : when fragment caching, blacklists fetch_attributes . Cannot combine with only
16
16
serializer . class_attribute :_cache_options # @api private : used by CachedSerializer, passed to _cache.fetch
17
17
# _cache_options include:
18
18
# expires_in
@@ -79,13 +79,6 @@ def non_cached_attributes
79
79
_attributes - cached_attributes
80
80
end
81
81
82
- # @api private
83
- # Used by FragmentCache on the CachedSerializer
84
- # to call attribute methods on the fragmented cached serializer.
85
- def fragmented ( serializer )
86
- self . _fragmented = serializer
87
- end
88
-
89
82
# Enables a serializer to be automatically cached
90
83
#
91
84
# Sets +::_cache+ object to <tt>ActionController::Base.cache_store</tt>
@@ -208,46 +201,44 @@ def object_cache_key(serializer, adapter_instance)
208
201
end
209
202
end
210
203
211
- def cached_attributes ( fields , cached_attributes , adapter_instance )
204
+ ### INSTANCE METHODS
205
+ def fetch_attributes ( fields , cached_attributes , adapter_instance )
212
206
if self . class . cache_enabled?
213
207
key = cache_key ( adapter_instance )
214
208
cached_attributes . fetch ( key ) do
215
- cache_check ( adapter_instance ) do
209
+ self . class . cache_store . fetch ( key , self . class . _cache_options ) do
216
210
attributes ( fields )
217
211
end
218
212
end
213
+ elsif self . class . fragment_cache_enabled?
214
+ fetch_fragment_cache ( adapter_instance )
219
215
else
220
- cache_check ( adapter_instance ) do
221
- attributes ( fields )
222
- end
216
+ attributes ( fields )
223
217
end
224
218
end
225
219
226
- def cache_check ( adapter_instance )
227
- if self . class . cache_enabled?
228
- self . class . cache_store . fetch ( cache_key ( adapter_instance ) , self . class . _cache_options ) do
220
+ def fetch ( adapter_instance , cache_options = self . class . _cache_options )
221
+ if self . class . cache_store
222
+ self . class . cache_store . fetch ( cache_key ( adapter_instance ) , cache_options ) do
229
223
yield
230
224
end
231
- elsif self . class . fragment_cache_enabled?
232
- fetch_fragment_cache ( adapter_instance )
233
225
else
234
226
yield
235
227
end
236
228
end
237
229
238
- # 1. Create a CachedSerializer and NonCachedSerializer from the serializer class
230
+ # 1. Create a CachedSerializer from the serializer class
239
231
# 2. Serialize the above two with the given adapter
240
232
# 3. Pass their serializations to the adapter +::fragment_cache+
241
233
#
242
234
# It will split the serializer into two, one that will be cached and one that will not
243
235
#
244
236
# Given a resource name
245
- # 1. Dynamically creates a CachedSerializer and NonCachedSerializer
237
+ # 1. Dynamically creates a CachedSerializer
246
238
# for a given class 'name'
247
239
# 2. Call
248
240
# CachedSerializer.cache(serializer._cache_options)
249
- # CachedSerializer.fragmented(serializer)
250
- # NonCachedSerializer.cache(serializer._cache_options)
241
+ # CachedSerializer._fragmented = serializer
251
242
# 3. Build a hash keyed to the +cached+ and +non_cached+ serializers
252
243
# 4. Call +cached_attributes+ on the serializer class and the above hash
253
244
# 5. Return the hash
@@ -256,61 +247,53 @@ def cache_check(adapter_instance)
256
247
# When +name+ is <tt>User::Admin</tt>
257
248
# creates the Serializer classes (if they don't exist).
258
249
# CachedUser_AdminSerializer
259
- # NonCachedUser_AdminSerializer
260
250
#
261
251
# Given a hash of its cached and non-cached serializers
262
252
# 1. Determine cached attributes from serializer class options
263
253
# 2. Add cached attributes to cached Serializer
264
254
# 3. Add non-cached attributes to non-cached Serializer
265
255
def fetch_fragment_cache ( adapter_instance )
266
- serializer_class_name = self . class . name . gsub ( '::' . freeze , '_' . freeze )
267
256
self . class . _cache_options ||= { }
268
257
self . class . _cache_options [ :key ] = self . class . _cache_key if self . class . _cache_key
269
258
270
- cached_serializer = _get_or_create_fragment_cached_serializer ( serializer_class_name )
259
+ cached_serializer = _get_or_create_fragment_cached_serializer
271
260
cached_hash = ActiveModelSerializers ::SerializableResource . new (
272
261
object ,
273
262
serializer : cached_serializer ,
274
263
adapter : adapter_instance . class
275
264
) . serializable_hash
276
265
277
- non_cached_serializer = _get_or_create_fragment_non_cached_serializer ( serializer_class_name )
278
- non_cached_hash = ActiveModelSerializers ::SerializableResource . new (
279
- object ,
280
- serializer : non_cached_serializer ,
281
- adapter : adapter_instance . class
282
- ) . serializable_hash
266
+ fields = self . class . non_cached_attributes
267
+ non_cached_hash = attributes ( fields , true )
283
268
284
269
# Merge both results
285
270
adapter_instance . fragment_cache ( cached_hash , non_cached_hash )
286
271
end
287
272
288
- def _get_or_create_fragment_cached_serializer ( serializer_class_name )
289
- cached_serializer = _get_or_create_fragment_serializer "Cached#{ serializer_class_name } "
290
- cached_serializer . cache ( self . class . _cache_options )
291
- cached_serializer . type ( self . class . _type )
292
- cached_serializer . fragmented ( self )
293
- self . class . cached_attributes . each do |attribute |
294
- options = self . class . _attributes_keys [ attribute ] || { }
295
- cached_serializer . attribute ( attribute , options )
296
- end
297
- cached_serializer
298
- end
299
-
300
- def _get_or_create_fragment_non_cached_serializer ( serializer_class_name )
301
- non_cached_serializer = _get_or_create_fragment_serializer "NonCached#{ serializer_class_name } "
302
- non_cached_serializer . type ( self . class . _type )
303
- non_cached_serializer . fragmented ( self )
304
- self . class . non_cached_attributes . each do |attribute |
305
- options = self . class . _attributes_keys [ attribute ] || { }
306
- non_cached_serializer . attribute ( attribute , options )
273
+ def _get_or_create_fragment_cached_serializer
274
+ serializer_class_name = self . class . name . gsub ( '::' . freeze , '_' . freeze )
275
+ cached_serializer_name = "Cached#{ serializer_class_name } "
276
+ if Object . const_defined? ( cached_serializer_name )
277
+ cached_serializer = Object . const_get ( cached_serializer_name )
278
+ # HACK: Test concern in production code :(
279
+ # But it's better than running all the cached fragment serializer
280
+ # code multiple times.
281
+ if Rails . env == 'test' . freeze
282
+ Object . send ( :remove_const , cached_serializer_name )
283
+ return _get_or_create_fragment_cached_serializer
284
+ end
285
+ cached_serializer
286
+ else
287
+ cached_serializer = Object . const_set ( cached_serializer_name , Class . new ( ActiveModel ::Serializer ) )
288
+ cached_serializer . cache ( self . class . _cache_options )
289
+ cached_serializer . type ( self . class . _type )
290
+ cached_serializer . _fragmented = self
291
+ self . class . cached_attributes . each do |attribute |
292
+ options = self . class . _attributes_keys [ attribute ] || { }
293
+ cached_serializer . attribute ( attribute , options )
294
+ end
295
+ cached_serializer
307
296
end
308
- non_cached_serializer
309
- end
310
-
311
- def _get_or_create_fragment_serializer ( name )
312
- return Object . const_get ( name ) if Object . const_defined? ( name )
313
- Object . const_set ( name , Class . new ( ActiveModel ::Serializer ) )
314
297
end
315
298
316
299
def cache_key ( adapter_instance )
0 commit comments