Permalink
Browse files

refactor the method cache objects to have a superclass

  • Loading branch information...
1 parent aa7b0ad commit efb6c16b40fe8f43341e4511fd811e58030a8afd @tenderlove tenderlove committed Jul 3, 2013
@@ -28,6 +28,31 @@ def self.set_name_cache(name, value)
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
@@ -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 @@ def initialize
# 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
@@ -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

0 comments on commit efb6c16

Please sign in to comment.