From 039e6eac34674606dcb9bd908f6dff52bdfaa826 Mon Sep 17 00:00:00 2001 From: Dylan Thacker-Smith Date: Wed, 15 Mar 2017 16:27:44 -0400 Subject: [PATCH 1/3] Backport caching of the constant lookup --- lib/active_model/serializable/utils.rb | 14 ++++++++------ lib/active_model/serializer.rb | 5 +++++ lib/active_model_serializers.rb | 3 +++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/active_model/serializable/utils.rb b/lib/active_model/serializable/utils.rb index efabb6c4..3b5f92c3 100644 --- a/lib/active_model/serializable/utils.rb +++ b/lib/active_model/serializable/utils.rb @@ -4,13 +4,15 @@ module ActiveModel extend self def _const_get(const) - begin - method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get - Object.send method, const - rescue NameError - const.safe_constantize + Serializer.serializers_cache.fetch_or_store(const) do + begin + method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get + Object.send method, const + rescue NameError + const.safe_constantize + end end end end end -end \ No newline at end of file +end diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 82693873..b5ff05da 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -4,6 +4,7 @@ require 'active_model/serializer/association' require 'active_model/serializer/config' require 'thread' +require 'concurrent/map' module ActiveModel class Serializer @@ -100,6 +101,10 @@ end associate(Association::HasMany, *attrs) end + def serializers_cache + @serializers_cache ||= Concurrent::Map.new + end + private def strip_attribute(attr) diff --git a/lib/active_model_serializers.rb b/lib/active_model_serializers.rb index 7066ebf4..8b50eb55 100644 --- a/lib/active_model_serializers.rb +++ b/lib/active_model_serializers.rb @@ -14,6 +14,9 @@ begin ActionController::Base.send(:include, ::ActionController::Serialization) ActionController::TestCase.send(:include, ::ActionController::SerializationAssertions) end + ActionDispatch::Reloader.to_prepare do + ActiveModel::Serializer.serializers_cache.clear + end end rescue LoadError # rails not installed, continuing From d02ee692aa96f33a218b3a734cf7e7160ac7e7c8 Mon Sep 17 00:00:00 2001 From: Dylan Thacker-Smith Date: Wed, 15 Mar 2017 17:16:57 -0400 Subject: [PATCH 2/3] Add explicit dependancy on concurrent-ruby --- active_model_serializers.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/active_model_serializers.gemspec b/active_model_serializers.gemspec index 2ad4ee54..39b8ba2a 100644 --- a/active_model_serializers.gemspec +++ b/active_model_serializers.gemspec @@ -21,5 +21,6 @@ Gem::Specification.new do |gem| gem.required_ruby_version = ">= 1.9.3" gem.add_dependency "activemodel", ">= 3.2" + gem.add_dependency "concurrent-ruby", "~> 1.0" gem.add_development_dependency "rails", ">= 3.2" end From d58a6e13b0c891efe8ce3b9375ad66804765663e Mon Sep 17 00:00:00 2001 From: Dylan Thacker-Smith Date: Wed, 15 Mar 2017 17:33:04 -0400 Subject: [PATCH 3/3] Move use of serializers cache out of Utils --- lib/active_model/serializable.rb | 6 +++++- lib/active_model/serializable/utils.rb | 14 ++++++-------- lib/active_model/serializer.rb | 5 ++++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/active_model/serializable.rb b/lib/active_model/serializable.rb index 344d8e4e..d23aae7d 100644 --- a/lib/active_model/serializable.rb +++ b/lib/active_model/serializable.rb @@ -33,7 +33,11 @@ module ActiveModel end def namespace - get_namespace && Utils._const_get(get_namespace) + if module_name = get_namespace + Serializer.serializers_cache.fetch_or_store(module_name) do + Utils._const_get(module_name) + end + end end def embedded_in_root_associations diff --git a/lib/active_model/serializable/utils.rb b/lib/active_model/serializable/utils.rb index 3b5f92c3..efabb6c4 100644 --- a/lib/active_model/serializable/utils.rb +++ b/lib/active_model/serializable/utils.rb @@ -4,15 +4,13 @@ module ActiveModel extend self def _const_get(const) - Serializer.serializers_cache.fetch_or_store(const) do - begin - method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get - Object.send method, const - rescue NameError - const.safe_constantize - end + begin + method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get + Object.send method, const + rescue NameError + const.safe_constantize end end end end -end +end \ No newline at end of file diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index b5ff05da..a89a79a8 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -66,7 +66,10 @@ end ArraySerializer end else - _const_get build_serializer_class(resource, options) + klass_name = build_serializer_class(resource, options) + Serializer.serializers_cache.fetch_or_store(klass_name) do + _const_get(klass_name) + end end end