diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2013-07-03 11:37:26 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2013-07-03 11:37:41 -0700 |
commit | efb6c16b40fe8f43341e4511fd811e58030a8afd (patch) | |
tree | 7312e39030335ecd584c43b9dd1ad37d03fb5bfe | |
parent | aa7b0ad428cdf38210f7654a4b48a154523dd235 (diff) | |
download | rails-efb6c16b40fe8f43341e4511fd811e58030a8afd.tar.gz rails-efb6c16b40fe8f43341e4511fd811e58030a8afd.tar.bz2 rails-efb6c16b40fe8f43341e4511fd811e58030a8afd.zip |
refactor the method cache objects to have a superclass
3 files changed, 41 insertions, 51 deletions
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 |