Skip to content

Commit d349490

Browse files
author
David Heinemeier Hansson
committed
Revert "Don't allocate new strings in compiled attribute methods"
This reverts commit f176501.
1 parent 750a30b commit d349490

File tree

2 files changed

+20
-39
lines changed

2 files changed

+20
-39
lines changed

activerecord/lib/active_record/attribute_methods/read.rb

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,36 +32,21 @@ def cache_attribute?(attr_name)
3232

3333
protected
3434

35-
# We want to generate the methods via module_eval rather than
36-
# define_method, because define_method is slower on dispatch and
37-
# uses more memory (because it creates a closure).
35+
# We want to generate the methods via module_eval rather than define_method,
36+
# because define_method is slower on dispatch and uses more memory (because it
37+
# creates a closure).
3838
#
39-
# But sometimes the database might return columns with
40-
# characters that are not allowed in normal method names (like
41-
# 'my_column(omg)'. So to work around this we first define with
42-
# the __temp__ identifier, and then use alias method to rename
43-
# it to what we want.
44-
#
45-
# We are also defining a constant to hold the frozen string of
46-
# the attribute name. Using a constant means that we do not have
47-
# to allocate an object on each call to the attribute method.
48-
# Making it frozen means that it doesn't get duped when used to
49-
# key the @attributes_cache in read_attribute.
50-
def define_method_attribute(name)
51-
safe_name = name.unpack('h*').first
39+
# But sometimes the database might return columns with characters that are not
40+
# allowed in normal method names (like 'my_column(omg)'. So to work around this
41+
# we first define with the __temp__ identifier, and then use alias method to
42+
# rename it to what we want.
43+
def define_method_attribute(attr_name)
5244
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
53-
module AttrNames
54-
unless defined? ATTR_#{safe_name}
55-
ATTR_#{safe_name} = #{name.inspect}.freeze
56-
end
45+
def __temp__
46+
read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) }
5747
end
58-
59-
def __temp__#{safe_name}
60-
read_attribute(AttrNames::ATTR_#{safe_name}) { |n| missing_attribute(n, caller) }
61-
end
62-
63-
alias_method #{name.inspect}, :__temp__#{safe_name}
64-
undef_method :__temp__#{safe_name}
48+
alias_method '#{attr_name}', :__temp__
49+
undef_method :__temp__
6550
STR
6651
end
6752

activerecord/lib/active_record/attribute_methods/write.rb

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,15 @@ module Write
99

1010
module ClassMethods
1111
protected
12-
13-
# See define_method_attribute in read.rb for an explanation of
14-
# this code.
15-
def define_method_attribute=(name)
16-
safe_name = name.unpack('h*').first
17-
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
18-
def __temp__#{safe_name}=(value)
19-
write_attribute(AttrNames::ATTR_#{safe_name}, value)
12+
def define_method_attribute=(attr_name)
13+
if attr_name =~ ActiveModel::AttributeMethods::NAME_COMPILABLE_REGEXP
14+
generated_attribute_methods.module_eval("def #{attr_name}=(new_value); write_attribute('#{attr_name}', new_value); end", __FILE__, __LINE__)
15+
else
16+
generated_attribute_methods.send(:define_method, "#{attr_name}=") do |new_value|
17+
write_attribute(attr_name, new_value)
18+
end
2019
end
21-
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
22-
undef_method :__temp__#{safe_name}=
23-
STR
24-
end
20+
end
2521
end
2622

2723
# Updates the attribute identified by <tt>attr_name</tt> with the

0 commit comments

Comments
 (0)