Skip to content

Commit d5833e8

Browse files
author
Yohan Robert
committed
Merge pull request #1480 from bf4/fix_cache_store
[FIX] The cache store needs to be the actually store, not e.g. :memory_store
2 parents a7a6841 + be9c1bd commit d5833e8

File tree

7 files changed

+48
-35
lines changed

7 files changed

+48
-35
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ Features:
2727
- [#1340](https://github.com/rails-api/active_model_serializers/pull/1340) Add support for resource-level meta. (@beauby)
2828

2929
Fixes:
30+
- [#1480](https://github.com/rails-api/active_model_serializers/pull/1480) Fix setting of cache_store from Rails configuration. (@bf4)
31+
Fix uninentional mutating of value in memory cache store. (@groyoh)
3032
- [#1622](https://github.com/rails-api/active_model_serializers/pull/1622) Fragment cache changed from per-record to per-serializer.
3133
Now, two serializers that use the same model may be separately cached. (@lserman)
3234
- [#1478](https://github.com/rails-api/active_model_serializers/pull/1478) Cache store will now be correctly set when serializers are

lib/active_model_serializers/adapter/attributes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def cached_attributes(cached_serializer)
5555
def serializable_hash_for_single_resource(options)
5656
resource = resource_object_for(options)
5757
relationships = resource_relationships(options)
58-
resource.merge!(relationships)
58+
resource.merge(relationships)
5959
end
6060

6161
def resource_relationships(options)

lib/active_model_serializers/railtie.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ class Railtie < Rails::Railtie
2525
# and also before eager_loading (if enabled).
2626
initializer 'active_model_serializers.set_configs', :after => 'action_controller.set_configs' do
2727
ActiveModelSerializers.logger = Rails.configuration.action_controller.logger
28-
ActiveModelSerializers.config.cache_store = Rails.configuration.action_controller.cache_store
2928
ActiveModelSerializers.config.perform_caching = Rails.configuration.action_controller.perform_caching
29+
# We want this hook to run after the config has been set, even if ActionController has already loaded.
30+
ActiveSupport.on_load(:action_controller) do
31+
ActiveModelSerializers.config.cache_store = cache_store
32+
end
3033
end
3134

3235
generators do |app|

test/cache_test.rb

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ class CacheTest < ActiveSupport::TestCase
99
attribute :special_attribute
1010
end
1111

12-
def setup
13-
ActionController::Base.cache_store.clear
12+
setup do
13+
cache_store.clear
1414
@comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
1515
@post = Post.new(title: 'New Post', body: 'Body')
1616
@bio = Bio.new(id: 1, content: 'AMS Contributor')
@@ -70,9 +70,9 @@ def test_override_cache_configuration
7070
end
7171

7272
def test_cache_definition
73-
assert_equal(ActionController::Base.cache_store, @post_serializer.class._cache)
74-
assert_equal(ActionController::Base.cache_store, @author_serializer.class._cache)
75-
assert_equal(ActionController::Base.cache_store, @comment_serializer.class._cache)
73+
assert_equal(cache_store, @post_serializer.class._cache)
74+
assert_equal(cache_store, @author_serializer.class._cache)
75+
assert_equal(cache_store, @comment_serializer.class._cache)
7676
end
7777

7878
def test_cache_key_definition
@@ -83,13 +83,13 @@ def test_cache_key_definition
8383

8484
def test_cache_key_interpolation_with_updated_at
8585
render_object_with_cache(@author)
86-
assert_equal(nil, ActionController::Base.cache_store.fetch(@author.cache_key))
87-
assert_equal(@author_serializer.attributes.to_json, ActionController::Base.cache_store.fetch("#{@author_serializer.class._cache_key}/#{@author_serializer.object.id}-#{@author_serializer.object.updated_at.strftime("%Y%m%d%H%M%S%9N")}").to_json)
86+
assert_equal(nil, cache_store.fetch(@author.cache_key))
87+
assert_equal(@author_serializer.attributes.to_json, cache_store.fetch("#{@author_serializer.class._cache_key}/#{@author_serializer.object.id}-#{@author_serializer.object.updated_at.strftime("%Y%m%d%H%M%S%9N")}").to_json)
8888
end
8989

9090
def test_default_cache_key_fallback
9191
render_object_with_cache(@comment)
92-
assert_equal(@comment_serializer.attributes.to_json, ActionController::Base.cache_store.fetch(@comment.cache_key).to_json)
92+
assert_equal(@comment_serializer.attributes.to_json, cache_store.fetch(@comment.cache_key).to_json)
9393
end
9494

9595
def test_cache_options_definition
@@ -104,41 +104,38 @@ def test_fragment_cache_definition
104104
end
105105

106106
def test_associations_separately_cache
107-
ActionController::Base.cache_store.clear
108-
assert_equal(nil, ActionController::Base.cache_store.fetch(@post.cache_key))
109-
assert_equal(nil, ActionController::Base.cache_store.fetch(@comment.cache_key))
107+
cache_store.clear
108+
assert_equal(nil, cache_store.fetch(@post.cache_key))
109+
assert_equal(nil, cache_store.fetch(@comment.cache_key))
110110

111111
Timecop.freeze(Time.current) do
112112
render_object_with_cache(@post)
113113

114-
assert_equal(@post_serializer.attributes, ActionController::Base.cache_store.fetch(@post.cache_key))
115-
assert_equal(@comment_serializer.attributes, ActionController::Base.cache_store.fetch(@comment.cache_key))
114+
assert_equal(@post_serializer.attributes, cache_store.fetch(@post.cache_key))
115+
assert_equal(@comment_serializer.attributes, cache_store.fetch(@comment.cache_key))
116116
end
117117
end
118118

119119
def test_associations_cache_when_updated
120-
# Clean the Cache
121-
ActionController::Base.cache_store.clear
122-
123120
Timecop.freeze(Time.current) do
124121
# Generate a new Cache of Post object and each objects related to it.
125122
render_object_with_cache(@post)
126123

127124
# Check if it cached the objects separately
128-
assert_equal(@post_serializer.attributes, ActionController::Base.cache_store.fetch(@post.cache_key))
129-
assert_equal(@comment_serializer.attributes, ActionController::Base.cache_store.fetch(@comment.cache_key))
125+
assert_equal(@post_serializer.attributes, cached_serialization(@post_serializer))
126+
assert_equal(@comment_serializer.attributes, cached_serialization(@comment_serializer))
130127

131128
# Simulating update on comments relationship with Post
132-
new_comment = Comment.new(id: 2, body: 'ZOMG A NEW COMMENT')
129+
new_comment = Comment.new(id: 2567, body: 'ZOMG A NEW COMMENT')
133130
new_comment_serializer = CommentSerializer.new(new_comment)
134131
@post.comments = [new_comment]
135132

136133
# Ask for the serialized object
137134
render_object_with_cache(@post)
138135

139136
# Check if the the new comment was cached
140-
assert_equal(new_comment_serializer.attributes, ActionController::Base.cache_store.fetch(new_comment.cache_key))
141-
assert_equal(@post_serializer.attributes, ActionController::Base.cache_store.fetch(@post.cache_key))
137+
assert_equal(new_comment_serializer.attributes, cached_serialization(new_comment_serializer))
138+
assert_equal(@post_serializer.attributes, cached_serialization(@post_serializer))
142139
end
143140
end
144141

@@ -153,7 +150,7 @@ def test_fragment_fetch_with_virtual_associations
153150
hash = render_object_with_cache(@location)
154151

155152
assert_equal(hash, expected_result)
156-
assert_equal({ place: 'Nowhere' }, ActionController::Base.cache_store.fetch(@location.cache_key))
153+
assert_equal({ place: 'Nowhere' }, cache_store.fetch(@location.cache_key))
157154
end
158155

159156
def test_fragment_cache_with_inheritance
@@ -166,11 +163,11 @@ def test_fragment_cache_with_inheritance
166163

167164
def test_uses_file_digest_in_cache_key
168165
render_object_with_cache(@blog)
169-
assert_equal(@blog_serializer.attributes, ActionController::Base.cache_store.fetch(@blog.cache_key_with_digest))
166+
assert_equal(@blog_serializer.attributes, cache_store.fetch(@blog.cache_key_with_digest))
170167
end
171168

172169
def test_cache_digest_definition
173-
assert_equal(::Model::FILE_DIGEST, @post_serializer.class._cache_digest)
170+
assert_equal(FILE_DIGEST, @post_serializer.class._cache_digest)
174171
end
175172

176173
def test_object_cache_keys
@@ -257,7 +254,16 @@ def test_warn_on_serializer_not_defined_in_file
257254
private
258255

259256
def render_object_with_cache(obj, options = {})
260-
SerializableResource.new(obj, options).serializable_hash
257+
serializable(obj, options).serializable_hash
258+
end
259+
260+
def cache_store
261+
ActiveModelSerializers.config.cache_store
262+
end
263+
264+
def cached_serialization(serializer)
265+
cache_key = CachedSerializer.new(serializer).cache_key
266+
cache_store.fetch(cache_key)
261267
end
262268
end
263269
end

test/fixtures/poro.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
verbose = $VERBOSE
22
$VERBOSE = nil
33
class Model < ActiveModelSerializers::Model
4-
FILE_DIGEST = Digest::MD5.hexdigest(File.open(__FILE__).read)
5-
64
### Helper methods, not required to be serializable
75

86
# Convenience when not adding @attributes readers and writers
@@ -21,10 +19,6 @@ def method_missing(meth, *args)
2119
def respond_to_missing?(method_name, _include_private = false)
2220
attributes.key?(method_name.to_s.tr('=', '').to_sym) || super
2321
end
24-
25-
def cache_key_with_digest
26-
"#{cache_key}/#{FILE_DIGEST}"
27-
end
2822
end
2923

3024
# see
@@ -58,7 +52,13 @@ class ProfilePreviewSerializer < ActiveModel::Serializer
5852
Like = Class.new(Model)
5953
Author = Class.new(Model)
6054
Bio = Class.new(Model)
61-
Blog = Class.new(Model)
55+
Blog = Class.new(Model) do
56+
FILE_DIGEST = Digest::MD5.hexdigest(File.open(__FILE__).read)
57+
58+
def cache_key_with_digest
59+
"#{cache_key}/#{FILE_DIGEST}"
60+
end
61+
end
6262
Role = Class.new(Model)
6363
User = Class.new(Model)
6464
Location = Class.new(Model)

test/serializers/caching_configuration_test_isolated.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class PerformCachingTrue < CachingConfigurationTest
3737
app.config.action_controller.perform_caching = true
3838
app.config.action_controller.cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
3939
end
40+
controller_cache_store # Force ActiveSupport.on_load(:action_controller) to run
4041
end
4142

4243
test 'it sets perform_caching to true on AMS.config and serializers' do
@@ -103,6 +104,7 @@ class PerformCachingFalse < CachingConfigurationTest
103104
app.config.action_controller.perform_caching = false
104105
app.config.action_controller.cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
105106
end
107+
controller_cache_store # Force ActiveSupport.on_load(:action_controller) to run
106108
end
107109

108110
test 'it sets perform_caching to false on AMS.config and serializers' do

test/support/rails_app.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module ActiveModelSerializers
55
config.secret_key_base = 'abc123'
66
config.active_support.test_order = :random
77
config.action_controller.perform_caching = true
8-
ActionController::Base.cache_store = :memory_store
8+
config.action_controller.cache_store = :memory_store
99
end
1010

1111
app.routes.default_url_options = { host: 'example.com' }

0 commit comments

Comments
 (0)