From cdab6f2b8a892375e638fa98c90ee2d420b116ec Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Thu, 28 Jan 2016 16:31:49 -0600 Subject: [PATCH] The cache store needs to be the actually store, not e.g. :memory_store Status quo in test app: In Rails ActionController::Base.cache_store = :memory_store and then AMS railtie does: ActiveModelSerializers.config.cache_store = config.action_controller.cache_store then, in the Railtie 1. ActiveSupport.on_load(:action_controller) fires - ActiveModelSerializers.config.cache_store #=> nil - ActionController::Base.cache_store #=> # # nil - ActionController::Base.cache_store #=> #ActiveSupport::Cache::MemoryStore entries=0, size=0, options={}>] 2. After set_configs fires - ActiveModelSerializers.config.cache_store #=> :memory_store 3. And we get a lot of failures: NoMethodError: undefined method `fetch' for :memory_store:Symbol So, we see that when we set the ActionController::Base.cache_store directly in our test app, we could set ActiveModelSerializers.config.cache_store in the :action_controller load hook, but that would never use the Rails config. To fix the Rails config, we change the config to the test app: config = Rails.configuration config.action_controller.cache_store = :memory_store and then AMS railtie does: ActiveModelSerializers.config.cache_store = ActiveSupport::Cache.lookup_store(config.action_controller.cache_store ActiveSupport.on_load(:action_controller) do ::ActiveModelSerializers.config.cache_store = cache_store end then 1. After set_configs fires - ActiveModelSerializers.config.cache_store #=> <#ActiveSupport::Cache::MemoryStore, object_id 70207113611740 2. ActiveSupport.on_load(:action_controller) fires - ActionController::Base.cache_store #=> <#ActiveSupport::Cache::MemoryStore, object_id 70207106279660 - ActiveModelSerializers.config.cache_store #=> <#ActiveSupport::Cache::MemoryStore, object_id 70207106279660 (notice the object_id changed) 3. And we get a failure: 1) Failure: ActiveModelSerializers::CacheTest#test_associations_cache_when_updated [active_model_serializers/test/cache_test.rb:141]: --- expected +++ actual @@ -1 +1 @@ -{:id=>"post", :title=>"New Post", :body=>"Body"} +{:id=>"post", :title=>"New Post", :body=>"Body", :comments=>[{:id=>2, :body=>"ZOMG A NEW COMMENT"}], :blog=>{:id=>999, :name=>"Custom blog"}, :author=>{:id=>"author", :name=>"Joao M. D. Moura"}} If we take out the on_load(:action_controller) hook, we get a ton of failures. So clearly, our code expects the controller cache to be the same as the serializer cache. So, we make sure we use an on_load(:action_controller) hook that runs after set_configs And look at the test and see it is filled with direct calls to ActionController::Base.cache_store assert_equal(new_comment_serializer.attributes, ActionController::Base.cache_store.fetch(new_comment.cache_key)) assert_equal(@post_serializer.attributes, ActionController::Base.cache_store.fetch(@post.cache_key)) But that's not a problem in this case, since they're the same object. For now, let's remove the :memory_store setting and use the default FileStore --- lib/active_model_serializers/railtie.rb | 5 ++++- test/serializers/caching_configuration_test_isolated.rb | 2 ++ test/support/rails_app.rb | 1 - 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/active_model_serializers/railtie.rb b/lib/active_model_serializers/railtie.rb index 1d95ceac..1c8ff3c9 100644 --- a/lib/active_model_serializers/railtie.rb +++ b/lib/active_model_serializers/railtie.rb @@ -25,8 +25,11 @@ module ActiveModelSerializers # and also before eager_loading (if enabled). initializer 'active_model_serializers.set_configs', :after => 'action_controller.set_configs' do ActiveModelSerializers.logger = Rails.configuration.action_controller.logger - ActiveModelSerializers.config.cache_store = Rails.configuration.action_controller.cache_store ActiveModelSerializers.config.perform_caching = Rails.configuration.action_controller.perform_caching + # We want this hook to run after the config has been set, even if ActionController has already loaded. + ActiveSupport.on_load(:action_controller) do + ActiveModelSerializers.config.cache_store = cache_store + end end generators do |app| diff --git a/test/serializers/caching_configuration_test_isolated.rb b/test/serializers/caching_configuration_test_isolated.rb index 1b6d5541..82e497b2 100644 --- a/test/serializers/caching_configuration_test_isolated.rb +++ b/test/serializers/caching_configuration_test_isolated.rb @@ -37,6 +37,7 @@ class CachingConfigurationTest < ActiveSupport::TestCase app.config.action_controller.perform_caching = true app.config.action_controller.cache_store = ActiveSupport::Cache.lookup_store(:memory_store) end + controller_cache_store # Force ActiveSupport.on_load(:action_controller) to run end test 'it sets perform_caching to true on AMS.config and serializers' do @@ -103,6 +104,7 @@ class CachingConfigurationTest < ActiveSupport::TestCase app.config.action_controller.perform_caching = false app.config.action_controller.cache_store = ActiveSupport::Cache.lookup_store(:memory_store) end + controller_cache_store # Force ActiveSupport.on_load(:action_controller) to run end test 'it sets perform_caching to false on AMS.config and serializers' do diff --git a/test/support/rails_app.rb b/test/support/rails_app.rb index bc2fc8d1..9d44a59a 100644 --- a/test/support/rails_app.rb +++ b/test/support/rails_app.rb @@ -5,7 +5,6 @@ module ActiveModelSerializers config.secret_key_base = 'abc123' config.active_support.test_order = :random config.action_controller.perform_caching = true - ActionController::Base.cache_store = :memory_store end app.routes.default_url_options = { host: 'example.com' }