Skip to content

Commit 0581c1a

Browse files
committed
use fetch rather than both Hash#key? and Hash#[]
1 parent 148f849 commit 0581c1a

File tree

1 file changed

+51
-49
lines changed
  • activerecord/lib/active_record/attribute_methods

1 file changed

+51
-49
lines changed

activerecord/lib/active_record/attribute_methods/read.rb

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -58,66 +58,68 @@ def type_cast_attribute(attr_name, attributes, cache = {}) #:nodoc:
5858
end
5959

6060
protected
61-
# We want to generate the methods via module_eval rather than define_method,
62-
# because define_method is slower on dispatch and uses more memory (because it
63-
# creates a closure).
64-
#
65-
# But sometimes the database might return columns with characters that are not
66-
# allowed in normal method names (like 'my_column(omg)'. So to work around this
67-
# we first define with the __temp__ identifier, and then use alias method to
68-
# rename it to what we want.
69-
def define_method_attribute(attr_name)
70-
cast_code = attribute_cast_code(attr_name)
71-
72-
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
73-
def __temp__
74-
#{internal_attribute_access_code(attr_name, cast_code)}
75-
end
76-
alias_method '#{attr_name}', :__temp__
77-
undef_method :__temp__
78-
STR
79-
80-
generated_external_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
81-
def __temp__(v, attributes, attributes_cache, attr_name)
82-
#{external_attribute_access_code(attr_name, cast_code)}
83-
end
84-
alias_method '#{attr_name}', :__temp__
85-
undef_method :__temp__
86-
STR
87-
end
61+
# We want to generate the methods via module_eval rather than define_method,
62+
# because define_method is slower on dispatch and uses more memory (because it
63+
# creates a closure).
64+
#
65+
# But sometimes the database might return columns with characters that are not
66+
# allowed in normal method names (like 'my_column(omg)'. So to work around this
67+
# we first define with the __temp__ identifier, and then use alias method to
68+
# rename it to what we want.
69+
def define_method_attribute(attr_name)
70+
cast_code = attribute_cast_code(attr_name)
71+
72+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
73+
def __temp__
74+
#{internal_attribute_access_code(attr_name, cast_code)}
75+
end
76+
alias_method '#{attr_name}', :__temp__
77+
undef_method :__temp__
78+
STR
8879

89-
private
90-
def cacheable_column?(column)
91-
attribute_types_cached_by_default.include?(column.type)
92-
end
80+
generated_external_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
81+
def __temp__(v, attributes, attributes_cache, attr_name)
82+
#{external_attribute_access_code(attr_name, cast_code)}
83+
end
84+
alias_method '#{attr_name}', :__temp__
85+
undef_method :__temp__
86+
STR
87+
end
9388

94-
def internal_attribute_access_code(attr_name, cast_code)
95-
access_code = "(v=@attributes[attr_name]) && #{cast_code}"
89+
private
90+
def cacheable_column?(column)
91+
attribute_types_cached_by_default.include?(column.type)
92+
end
9693

97-
unless attr_name == primary_key
98-
access_code.insert(0, "missing_attribute(attr_name, caller) unless @attributes.has_key?(attr_name); ")
99-
end
94+
def internal_attribute_access_code(attr_name, cast_code)
95+
if attr_name == primary_key
96+
access_code = "v = @attributes[attr_name];"
97+
else
98+
access_code = "v = @attributes.fetch(attr_name) { missing_attribute(attr_name, caller) };"
99+
end
100100

101-
if cache_attribute?(attr_name)
102-
access_code = "@attributes_cache[attr_name] ||= (#{access_code})"
103-
end
101+
access_code << "v && #{cast_code};"
104102

105-
"attr_name = '#{attr_name}'; #{access_code}"
103+
if cache_attribute?(attr_name)
104+
access_code = "@attributes_cache[attr_name] ||= (#{access_code})"
106105
end
107106

108-
def external_attribute_access_code(attr_name, cast_code)
109-
access_code = "v && #{cast_code}"
107+
"attr_name = '#{attr_name}'; #{access_code}"
108+
end
110109

111-
if cache_attribute?(attr_name)
112-
access_code = "attributes_cache[attr_name] ||= (#{access_code})"
113-
end
110+
def external_attribute_access_code(attr_name, cast_code)
111+
access_code = "v && #{cast_code}"
114112

115-
access_code
113+
if cache_attribute?(attr_name)
114+
access_code = "attributes_cache[attr_name] ||= (#{access_code})"
116115
end
117116

118-
def attribute_cast_code(attr_name)
119-
columns_hash[attr_name].type_cast_code('v')
120-
end
117+
access_code
118+
end
119+
120+
def attribute_cast_code(attr_name)
121+
columns_hash[attr_name].type_cast_code('v')
122+
end
121123
end
122124

123125
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,

0 commit comments

Comments
 (0)