From efb6c16b40fe8f43341e4511fd811e58030a8afd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 3 Jul 2013 11:37:26 -0700 Subject: refactor the method cache objects to have a superclass --- .../lib/active_record/attribute_methods.rb | 25 ++++++++++++++++ .../lib/active_record/attribute_methods/read.rb | 34 +++++----------------- .../lib/active_record/attribute_methods/write.rb | 33 +++++---------------- 3 files changed, 41 insertions(+), 51 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 2fd2ea896b..c07fd67216 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -28,6 +28,31 @@ module ActiveRecord end } + class AttributeMethodCache + include Mutex_m + + def initialize + super + @module = Module.new + @method_cache = {} + end + + def [](name) + synchronize do + @method_cache.fetch(name) { + safe_name = name.unpack('h*').first + temp_method = "__temp__#{safe_name}" + ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name + @module.module_eval method_body(temp_method, safe_name), __FILE__, __LINE__ + @method_cache[name] = @module.instance_method temp_method + } + end + end + + private + def method_body; raise NotImplementedError; end + end + module ClassMethods def inherited(child_class) #:nodoc: child_class.initialize_generated_modules diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index d43f4b55e8..c7d861a957 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -1,15 +1,8 @@ module ActiveRecord module AttributeMethods module Read - ReaderMethodCache = Class.new { - include Mutex_m - - def initialize - super - @module = Module.new - @method_cache = {} - end - + ReaderMethodCache = Class.new(AttributeMethodCache) { + private # We want to generate the methods via module_eval rather than # define_method, because define_method is slower on dispatch. # Evaluating many similar methods may use more memory as the instruction @@ -28,24 +21,13 @@ module ActiveRecord # to allocate an object on each call to the attribute method. # Making it frozen means that it doesn't get duped when used to # key the @attributes_cache in read_attribute. - def [](name) - synchronize do - @method_cache.fetch(name) { - safe_name = name.unpack('h*').first - temp_method = "__temp__#{safe_name}" - - ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name - - @module.module_eval <<-STR, __FILE__, __LINE__ + 1 - def #{temp_method} - name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name} - read_attribute(name) { |n| missing_attribute(n, caller) } - end - STR - - @method_cache[name] = @module.instance_method temp_method - } + def method_body(method_name, const_name) + <<-EOMETHOD + def #{method_name} + name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{const_name} + read_attribute(name) { |n| missing_attribute(n, caller) } end + EOMETHOD end }.new diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index 813a85d2f7..f865f0b2c8 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -1,33 +1,16 @@ module ActiveRecord module AttributeMethods module Write - WriterMethodCache = Class.new { - include Mutex_m + WriterMethodCache = Class.new(AttributeMethodCache) { + private - def initialize - super - @module = Module.new - @method_cache = {} - end - - def [](name) - synchronize do - @method_cache.fetch(name) { - safe_name = name.unpack('h*').first - temp_method = "__temp__#{safe_name}=" - - ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name - - @module.module_eval <<-STR, __FILE__, __LINE__ + 1 - def #{temp_method}(value) - name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name} - write_attribute(name, value) - end - STR - - @method_cache[name] = @module.instance_method temp_method - } + def method_body(method_name, const_name) + <<-EOMETHOD + def #{method_name}(value) + name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{const_name} + write_attribute(name, value) end + EOMETHOD end }.new -- cgit v1.2.3