Skip to content

Commit 913f396

Browse files
committed
Move adapter cache properties to class level (where they belong).
1 parent 516e7da commit 913f396

File tree

6 files changed

+84
-67
lines changed

6 files changed

+84
-67
lines changed

lib/active_model/serializer.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ def self.include_directive_from_options(options)
109109
end
110110
end
111111

112+
def self.serialization_adapter_instance
113+
@serialization_adapter_instance ||= ActiveModelSerializers::Adapter::Attributes
114+
end
115+
112116
attr_accessor :object, :root, :scope
113117

114118
# `scope_name` is set as :current_user by default in the controller.
@@ -163,8 +167,7 @@ def success?
163167
def serializable_hash(adapter_opts = nil)
164168
adapter_opts ||= {}
165169
adapter_opts = { include: '*' }.merge!(adapter_opts)
166-
adapter_instance = ActiveModelSerializers::Adapter::Attributes.new(self, adapter_opts)
167-
serialize(adapter_opts, {}, adapter_instance)
170+
serialize(adapter_opts)
168171
end
169172
alias to_hash serializable_hash
170173
alias to_h serializable_hash
@@ -197,7 +200,7 @@ def read_attribute_for_serialization(attr)
197200
end
198201

199202
# @api private
200-
def serialize(adapter_options, options, adapter_instance)
203+
def serialize(adapter_options, options = {}, adapter_instance = self.class.serialization_adapter_instance)
201204
options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
202205
cached_attributes = adapter_options[:cached_attributes] ||= {}
203206
resource = cached_attributes(options[:fields], cached_attributes, adapter_instance)

lib/active_model/serializer/caching.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ def cache_key(adapter_instance)
318318

319319
parts = []
320320
parts << object_cache_key
321-
parts << adapter_instance.cached_name
321+
parts << adapter_instance.cache_key
322322
parts << self.class._cache_digest unless self.class._skip_digest?
323323
@cache_key = parts.join('/')
324324
end

lib/active_model_serializers/adapter.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ def register(name, klass = name)
5151
self
5252
end
5353

54+
def registered_name(adapter_class)
55+
ADAPTER_MAP.key adapter_class
56+
end
57+
5458
# @param adapter [String, Symbol, Class] name to fetch adapter by
5559
# @return [ActiveModelSerializers::Adapter] subclass of Adapter
5660
# @raise [UnknownAdapterError]

lib/active_model_serializers/adapter/base.rb

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,47 @@ def self.inherited(subclass)
88
ActiveModelSerializers::Adapter.register(subclass)
99
end
1010

11+
# Sets the default transform for the adapter.
12+
#
13+
# @return [Symbol] the default transform for the adapter
14+
def self.default_key_transform
15+
:unaltered
16+
end
17+
18+
# Determines the transform to use in order of precedence:
19+
# adapter option, global config, adapter default.
20+
#
21+
# @param options [Object]
22+
# @return [Symbol] the transform to use
23+
def self.transform(options)
24+
return options[:key_transform] if options && options[:key_transform]
25+
ActiveModelSerializers.config.key_transform || default_key_transform
26+
end
27+
28+
# Transforms the casing of the supplied value.
29+
#
30+
# @param value [Object] the value to be transformed
31+
# @param options [Object] serializable resource options
32+
# @return [Symbol] the default transform for the adapter
33+
def self.transform_key_casing!(value, options)
34+
KeyTransform.send(transform(options), value)
35+
end
36+
37+
def self.cache_key
38+
@cache_key ||= ActiveModelSerializers::Adapter.registered_name(self)
39+
end
40+
41+
def self.fragment_cache(cached_hash, non_cached_hash)
42+
non_cached_hash.merge cached_hash
43+
end
44+
1145
attr_reader :serializer, :instance_options
1246

1347
def initialize(serializer, options = {})
1448
@serializer = serializer
1549
@instance_options = options
1650
end
1751

18-
def cached_name
19-
@cached_name ||= self.class.name.demodulize.underscore
20-
end
21-
2252
# Subclasses that implement this method must first call
2353
# options = serialization_options(options)
2454
def serializable_hash(_options = nil)
@@ -29,8 +59,12 @@ def as_json(options = nil)
2959
serializable_hash(options)
3060
end
3161

62+
def cache_key
63+
self.class.cache_key
64+
end
65+
3266
def fragment_cache(cached_hash, non_cached_hash)
33-
non_cached_hash.merge cached_hash
67+
self.class.fragment_cache(cached_hash, non_cached_hash)
3468
end
3569

3670
private
@@ -44,34 +78,6 @@ def serialization_options(options)
4478
def root
4579
serializer.json_key.to_sym if serializer.json_key
4680
end
47-
48-
class << self
49-
# Sets the default transform for the adapter.
50-
#
51-
# @return [Symbol] the default transform for the adapter
52-
def default_key_transform
53-
:unaltered
54-
end
55-
56-
# Determines the transform to use in order of precedence:
57-
# adapter option, global config, adapter default.
58-
#
59-
# @param options [Object]
60-
# @return [Symbol] the transform to use
61-
def transform(options)
62-
return options[:key_transform] if options && options[:key_transform]
63-
ActiveModelSerializers.config.key_transform || default_key_transform
64-
end
65-
66-
# Transforms the casing of the supplied value.
67-
#
68-
# @param value [Object] the value to be transformed
69-
# @param options [Object] serializable resource options
70-
# @return [Symbol] the default transform for the adapter
71-
def transform_key_casing!(value, options)
72-
KeyTransform.send(transform(options), value)
73-
end
74-
end
7581
end
7682
end
7783
end

lib/active_model_serializers/adapter/json_api.rb

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,27 @@ class JsonApi < Base
3131
autoload :Error
3232
autoload :Deserialization
3333

34+
def self.default_key_transform
35+
:dash
36+
end
37+
38+
def self.fragment_cache(cached_hash, non_cached_hash, root = true)
39+
core_cached = cached_hash.first
40+
core_non_cached = non_cached_hash.first
41+
no_root_cache = cached_hash.delete_if { |key, _value| key == core_cached[0] }
42+
no_root_non_cache = non_cached_hash.delete_if { |key, _value| key == core_non_cached[0] }
43+
cached_resource = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1]
44+
hash = root ? { root => cached_resource } : cached_resource
45+
46+
hash.deep_merge no_root_non_cache.deep_merge no_root_cache
47+
end
48+
3449
def initialize(serializer, options = {})
3550
super
3651
@include_directive = JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
3752
@fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields))
3853
end
3954

40-
def self.default_key_transform
41-
:dash
42-
end
43-
4455
# {http://jsonapi.org/format/#crud Requests are transactional, i.e. success or failure}
4556
# {http://jsonapi.org/format/#document-top-level data and errors MUST NOT coexist in the same document.}
4657
def serializable_hash(*)
@@ -52,6 +63,11 @@ def serializable_hash(*)
5263
self.class.transform_key_casing!(document, instance_options)
5364
end
5465

66+
def fragment_cache(cached_hash, non_cached_hash)
67+
root = !instance_options.include?(:include)
68+
self.class.fragment_cache(cached_hash, non_cached_hash, root)
69+
end
70+
5571
# {http://jsonapi.org/format/#document-top-level Primary data}
5672
# definition:
5773
# ☐ toplevel_data (required)
@@ -174,18 +190,6 @@ def failure_document
174190
hash
175191
end
176192

177-
def fragment_cache(cached_hash, non_cached_hash)
178-
root = false if instance_options.include?(:include)
179-
core_cached = cached_hash.first
180-
core_non_cached = non_cached_hash.first
181-
no_root_cache = cached_hash.delete_if { |key, _value| key == core_cached[0] }
182-
no_root_non_cache = non_cached_hash.delete_if { |key, _value| key == core_non_cached[0] }
183-
cached_resource = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1]
184-
hash = root ? { root => cached_resource } : cached_resource
185-
186-
hash.deep_merge no_root_non_cache.deep_merge no_root_cache
187-
end
188-
189193
protected
190194

191195
attr_reader :fieldset

test/cache_test.rb

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ def test_cache_key_interpolation_with_updated_at_when_cache_key_is_not_defined_o
102102

103103
render_object_with_cache(uncached_author)
104104
key = "#{uncached_author_serializer.class._cache_key}/#{uncached_author_serializer.object.id}-#{uncached_author_serializer.object.updated_at.strftime("%Y%m%d%H%M%S%9N")}"
105-
key = "#{key}/#{adapter.cached_name}"
105+
key = "#{key}/#{adapter.cache_key}"
106106
assert_equal(uncached_author_serializer.attributes.to_json, cache_store.fetch(key).to_json)
107107
end
108108

109109
def test_default_cache_key_fallback
110110
render_object_with_cache(@comment)
111-
key = "#{@comment.cache_key}/#{adapter.cached_name}"
111+
key = "#{@comment.cache_key}/#{adapter.cache_key}"
112112
assert_equal(@comment_serializer.attributes.to_json, cache_store.fetch(key).to_json)
113113
end
114114

@@ -139,9 +139,9 @@ def test_associations_separately_cache
139139
Timecop.freeze(Time.current) do
140140
render_object_with_cache(@post)
141141

142-
key = "#{@post.cache_key}/#{adapter.cached_name}"
142+
key = "#{@post.cache_key}/#{adapter.cache_key}"
143143
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
144-
key = "#{@comment.cache_key}/#{adapter.cached_name}"
144+
key = "#{@comment.cache_key}/#{adapter.cache_key}"
145145
assert_equal(@comment_serializer.attributes, cache_store.fetch(key))
146146
end
147147
end
@@ -152,9 +152,9 @@ def test_associations_cache_when_updated
152152
render_object_with_cache(@post)
153153

154154
# Check if it cached the objects separately
155-
key = "#{@post.cache_key}/#{adapter.cached_name}"
155+
key = "#{@post.cache_key}/#{adapter.cache_key}"
156156
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
157-
key = "#{@comment.cache_key}/#{adapter.cached_name}"
157+
key = "#{@comment.cache_key}/#{adapter.cache_key}"
158158
assert_equal(@comment_serializer.attributes, cache_store.fetch(key))
159159

160160
# Simulating update on comments relationship with Post
@@ -166,9 +166,9 @@ def test_associations_cache_when_updated
166166
render_object_with_cache(@post)
167167

168168
# Check if the the new comment was cached
169-
key = "#{new_comment.cache_key}/#{adapter.cached_name}"
169+
key = "#{new_comment.cache_key}/#{adapter.cache_key}"
170170
assert_equal(new_comment_serializer.attributes, cache_store.fetch(key))
171-
key = "#{@post.cache_key}/#{adapter.cached_name}"
171+
key = "#{@post.cache_key}/#{adapter.cache_key}"
172172
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
173173
end
174174
end
@@ -184,7 +184,7 @@ def test_fragment_fetch_with_virtual_associations
184184
hash = render_object_with_cache(@location)
185185

186186
assert_equal(hash, expected_result)
187-
key = "#{@location.cache_key}/#{adapter.cached_name}"
187+
key = "#{@location.cache_key}/#{adapter.cache_key}"
188188
assert_equal({ place: 'Nowhere' }, cache_store.fetch(key))
189189
end
190190

@@ -276,7 +276,7 @@ def test_a_serializer_rendered_by_two_adapter_returns_differently_cached_attribu
276276

277277
def test_uses_file_digest_in_cache_key
278278
render_object_with_cache(@blog)
279-
key = "#{@blog.cache_key}/#{adapter.cached_name}/#{::Model::FILE_DIGEST}"
279+
key = "#{@blog.cache_key}/#{adapter.cache_key}/#{::Model::FILE_DIGEST}"
280280
assert_equal(@blog_serializer.attributes, cache_store.fetch(key))
281281
end
282282

@@ -291,7 +291,7 @@ def test_object_cache_keys
291291
actual = ActiveModel::Serializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_directive)
292292

293293
assert_equal 3, actual.size
294-
assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cached_name}" }
294+
assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cache_key}" }
295295
assert actual.any? { |key| key =~ %r{post/post-\d+} }
296296
assert actual.any? { |key| key =~ %r{author/author-\d+} }
297297
end
@@ -306,13 +306,13 @@ def test_cached_attributes
306306
include_directive = ActiveModelSerializers.default_include_directive
307307
cached_attributes = ActiveModel::Serializer.cache_read_multi(serializer, attributes, include_directive)
308308

309-
assert_equal cached_attributes["#{@comment.cache_key}/#{attributes.cached_name}"], Comment.new(id: 1, body: 'ZOMG A COMMENT').attributes
310-
assert_equal cached_attributes["#{@comment.post.cache_key}/#{attributes.cached_name}"], Post.new(id: 'post', title: 'New Post', body: 'Body').attributes
309+
assert_equal cached_attributes["#{@comment.cache_key}/#{attributes.cache_key}"], Comment.new(id: 1, body: 'ZOMG A COMMENT').attributes
310+
assert_equal cached_attributes["#{@comment.post.cache_key}/#{attributes.cache_key}"], Post.new(id: 'post', title: 'New Post', body: 'Body').attributes
311311

312312
writer = @comment.post.blog.writer
313313
writer_cache_key = writer.cache_key
314314

315-
assert_equal cached_attributes["#{writer_cache_key}/#{attributes.cached_name}"], Author.new(id: 'author', name: 'Joao M. D. Moura').attributes
315+
assert_equal cached_attributes["#{writer_cache_key}/#{attributes.cache_key}"], Author.new(id: 'author', name: 'Joao M. D. Moura').attributes
316316
end
317317
end
318318

0 commit comments

Comments
 (0)