diff options
Diffstat (limited to 'activerecord/lib/active_record/attribute_methods/read.rb')
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/read.rb | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 69d5cd83f1..a248eb3a7b 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -43,7 +43,7 @@ module ActiveRecord end if attr_name == primary_key && attr_name != "id" - define_read_method(:id, attr_name, columns_hash[attr_name]) + define_read_method('id', attr_name, columns_hash[attr_name]) end end @@ -59,7 +59,9 @@ module ActiveRecord end # Define an attribute reader method. Cope with nil column. - def define_read_method(symbol, attr_name, column) + # method_name is the same as attr_name except when a non-standard primary key is used, + # we still define #id as an accessor for the key + def define_read_method(method_name, attr_name, column) cast_code = column.type_cast_code('v') access_code = "(v=@attributes['#{attr_name}']) && #{cast_code}" @@ -70,12 +72,25 @@ module ActiveRecord if cache_attribute?(attr_name) access_code = "@attributes_cache['#{attr_name}'] ||= (#{access_code})" end - if symbol =~ /^[a-zA-Z_]\w*[!?=]?$/ - generated_attribute_methods.module_eval("def _#{symbol}; #{access_code}; end; alias #{symbol} _#{symbol}", __FILE__, __LINE__) + + # Where possible, generate the method by evalling a string, as this will result in + # faster accesses because it avoids the block eval and then string eval incurred + # by the second branch. + # + # The second, slower, branch is necessary to support instances where the database + # returns columns with extra stuff in (like 'my_column(omg)'). + if method_name =~ /^[a-zA-Z_]\w*[!?=]?$/ + generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + def _#{method_name} + #{access_code} + end + + alias #{method_name} _#{method_name} + STR else generated_attribute_methods.module_eval do - define_method("_#{symbol}") { eval(access_code) } - alias_method(symbol, "_#{symbol}") + define_method("_#{method_name}") { eval(access_code) } + alias_method(method_name, "_#{method_name}") end end end @@ -84,9 +99,11 @@ module ActiveRecord # 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) - send "_#{attr_name}" - rescue NoMethodError - _read_attribute attr_name + if respond_to? "_#{attr_name}" + send "_#{attr_name}" if @attributes.has_key?(attr_name.to_s) + else + _read_attribute attr_name + end end def _read_attribute(attr_name) |