much code can be deleted thanks to @tenderlove's refactoring

This commit is contained in:
Jon Leighton 2012-03-28 16:38:05 +01:00
parent 9897b9a689
commit 6cff09038d
3 changed files with 6 additions and 72 deletions

View File

@ -49,14 +49,6 @@ module ActiveRecord
@attribute_methods_generated ||= false
end
# We will define the methods as instance methods, but will call them as singleton
# methods. This allows us to use method_defined? to check if the method exists,
# which is fast and won't give any false positives from the ancestors (because
# there are no ancestors).
def generated_external_attribute_methods
@generated_external_attribute_methods ||= Module.new { extend self }
end
def undefine_attribute_methods
super if attribute_methods_generated?
@attribute_methods_generated = false

View File

@ -43,12 +43,6 @@ module ActiveRecord
if attr_name == primary_key && attr_name != 'id'
generated_attribute_methods.send(:alias_method, :id, primary_key)
generated_external_attribute_methods.module_eval <<-CODE, __FILE__, __LINE__
def id(v, attributes, attributes_cache, attr_name)
attr_name = '#{primary_key}'
send(attr_name, attributes[attr_name], attributes, attributes_cache, attr_name)
end
CODE
end
end

View File

@ -29,35 +29,8 @@ module ActiveRecord
cached_attributes.include?(attr_name)
end
def undefine_attribute_methods
generated_external_attribute_methods.module_eval do
instance_methods.each { |m| undef_method(m) }
end
super
end
def type_cast_attribute(attr_name, attributes, cache = {}) #:nodoc:
return unless attr_name
attr_name = attr_name.to_s
if generated_external_attribute_methods.method_defined?(attr_name)
if attributes.has_key?(attr_name) || attr_name == 'id'
generated_external_attribute_methods.send(attr_name, attributes[attr_name], attributes, cache, attr_name)
end
elsif !attribute_methods_generated?
# If we haven't generated the caster methods yet, do that and
# then try again
define_attribute_methods
type_cast_attribute(attr_name, attributes, cache)
else
# If we get here, the attribute has no associated DB column, so
# just return it verbatim.
attributes[attr_name]
end
end
protected
# We want to generate the methods via module_eval rather than define_method,
# because define_method is slower on dispatch and uses more memory (because it
# creates a closure).
@ -67,19 +40,9 @@ module ActiveRecord
# we first define with the __temp__ identifier, and then use alias method to
# rename it to what we want.
def define_method_attribute(attr_name)
cast_code = attribute_cast_code(attr_name)
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
def __temp__
#{internal_attribute_access_code(attr_name, cast_code)}
end
alias_method '#{attr_name}', :__temp__
undef_method :__temp__
STR
generated_external_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
def __temp__(v, attributes, attributes_cache, attr_name)
#{external_attribute_access_code(attr_name, cast_code)}
read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) }
end
alias_method '#{attr_name}', :__temp__
undef_method :__temp__
@ -87,6 +50,7 @@ module ActiveRecord
end
private
def cacheable_column?(column)
if attribute_types_cached_by_default == ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
! serialized_attributes.include? column.name
@ -94,24 +58,6 @@ module ActiveRecord
attribute_types_cached_by_default.include?(column.type)
end
end
def internal_attribute_access_code(attr_name, cast_code)
"read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) }"
end
def external_attribute_access_code(attr_name, cast_code)
access_code = "v && #{cast_code}"
if cache_attribute?(attr_name)
access_code = "attributes_cache[attr_name] ||= (#{access_code})"
end
access_code
end
def attribute_cast_code(attr_name)
columns_hash[attr_name].type_cast_code('v')
end
end
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
@ -120,7 +66,9 @@ module ActiveRecord
# If it's cached, just return it
@attributes_cache.fetch(attr_name.to_s) { |name|
column = @columns_hash.fetch(name) {
return self.class.type_cast_attribute(name, @attributes, @attributes_cache)
return @attributes.fetch(name) {
@attributes[self.class.primary_key] if name == 'id'
}
}
value = @attributes.fetch(name) {