Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Key the attributes hash with symbols

This is a performance/GC optimisation.

In theory, this could be optimised by the implementation (last time I
checked, this would have no effect on JRuby). But in practise, this make
attribute access faster.
  • Loading branch information...
commit 86c3dfbd47cb96af02daaa655963292b1a1b110e 1 parent e96558f
@jonleighton jonleighton authored
View
13 activerecord/lib/active_record/attribute_methods/read.rb
@@ -45,7 +45,7 @@ def cache_attribute?(attr_name)
def define_method_attribute(attr_name)
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
def __temp__
- read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) }
+ read_attribute(:'#{attr_name}') { |n| missing_attribute(n, caller) }
end
alias_method '#{attr_name}', :__temp__
undef_method :__temp__
@@ -68,11 +68,16 @@ def cacheable_column?(column)
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
def read_attribute(attr_name)
+ return unless attr_name
+ name_sym = attr_name.to_sym
+
# If it's cached, just return it
- @attributes_cache.fetch(attr_name.to_s) { |name|
+ @attributes_cache.fetch(name_sym) {
+ name = attr_name.to_s
+
column = @columns_hash.fetch(name) {
return @attributes.fetch(name) {
- if name == 'id' && self.class.primary_key != name
+ if name_sym == :id && self.class.primary_key != name
read_attribute(self.class.primary_key)
end
}
@@ -83,7 +88,7 @@ def read_attribute(attr_name)
}
if self.class.cache_attribute?(name)
- @attributes_cache[name] = column.type_cast(value)
+ @attributes_cache[name_sym] = column.type_cast(value)
else
column.type_cast value
end
View
2  activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -65,7 +65,7 @@ def #{attr_name}=(original_time)
if (rounded_value != rounded_time) || (!rounded_value && original_time)
write_attribute("#{attr_name}", original_time)
#{attr_name}_will_change!
- @attributes_cache["#{attr_name}"] = zoned_time
+ @attributes_cache[:"#{attr_name}"] = zoned_time
end
end
EOV
View
4 activerecord/lib/active_record/attribute_methods/write.rb
@@ -25,13 +25,13 @@ def define_method_attribute=(attr_name)
def write_attribute(attr_name, value)
attr_name = attr_name.to_s
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
- @attributes_cache.delete(attr_name)
+ @attributes_cache.delete(attr_name.to_sym)
column = column_for_attribute(attr_name)
# If we're dealing with a binary column, write the data to the cache
# so we don't attempt to typecast multiple times.
if column && column.binary?
- @attributes_cache[attr_name] = value
+ @attributes_cache[attr_name.to_sym] = value
end
if column || @attributes.has_key?(attr_name)
View
4 activerecord/test/cases/attribute_methods_test.rb
@@ -542,10 +542,10 @@ def test_accessing_cached_attributes_caches_the_converted_values_and_nothing_els
val = t.send attr_name unless attr_name == "type"
if attribute_gets_cached
assert cached_columns.include?(attr_name)
- assert_equal val, cache[attr_name]
+ assert_equal val, cache[attr_name.to_sym]
else
assert uncached_columns.include?(attr_name)
- assert !cache.include?(attr_name)
+ assert !cache.include?(attr_name.to_sym)
end
end
end

3 comments on commit 86c3dfb

@andreacampi

I was wondering, why the mix of var.to_sym and :"#{var}" ?

@jonleighton
Collaborator

:'#{var}' is used in generated code.

@andreacampi

Oh, got it. My bad for looking at just the diff instead of the whole file.

Please sign in to comment.
Something went wrong with that request. Please try again.