From a9f3c9da01d721963d05949604ead909aaabbf36 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Mon, 11 Apr 2011 00:52:42 +0800 Subject: Using Object#in? and Object#either? in various places There're a lot of places in Rails source code which make a lot of sense to switching to Object#in? or Object#either? instead of using [].include?. --- .../lib/active_record/attribute_methods/time_zone_conversion.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/attribute_methods') diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index 6aac96df6f..032a3135f0 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/object/inclusion' module ActiveRecord module AttributeMethods @@ -58,7 +59,7 @@ module ActiveRecord private def create_time_zone_conversion_attribute?(name, column) - time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && [:datetime, :timestamp].include?(column.type) + time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && column.type.either?(:datetime, :timestamp) end end end -- cgit v1.2.3 From d1575ae1b9658c91145d6a46ec2a144a5a089207 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 12 Apr 2011 00:23:07 +0200 Subject: Change Object#either? to Object#among? -- thanks to @jamesarosen for the suggestion! --- .../lib/active_record/attribute_methods/time_zone_conversion.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/attribute_methods') diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index 032a3135f0..67b0e77a25 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -59,7 +59,7 @@ module ActiveRecord private def create_time_zone_conversion_attribute?(name, column) - time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && column.type.either?(:datetime, :timestamp) + time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && column.type.among?(:datetime, :timestamp) end end end -- cgit v1.2.3 From 733bfa63f5d8d3b963202b6d3e9f00b4db070b91 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Wed, 13 Apr 2011 00:04:40 +0800 Subject: Remove `#among?` from Active Support After a long list of discussion about the performance problem from using varargs and the reason that we can't find a great pair for it, it would be best to remove support for it for now. It will come back if we can find a good pair for it. For now, Bon Voyage, `#among?`. --- .../lib/active_record/attribute_methods/time_zone_conversion.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/attribute_methods') diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index 67b0e77a25..62a3cfa9a5 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -59,7 +59,7 @@ module ActiveRecord private def create_time_zone_conversion_attribute?(name, column) - time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && column.type.among?(:datetime, :timestamp) + time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && column.type.in?([:datetime, :timestamp]) end end end -- cgit v1.2.3 From 93641ed6c8c684f6b4db02b6c8a22fa9bc7f0eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stian=20Gryt=C3=B8yr?= Date: Thu, 14 Apr 2011 16:31:08 +0200 Subject: Fixes performance issue introduced in 3.0.6 (issue #6695) --- activerecord/lib/active_record/attribute_methods/read.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record/attribute_methods') diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 69d5cd83f1..43f736c89c 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -84,9 +84,11 @@ module ActiveRecord # Returns the value of the attribute identified by attr_name 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}" + else + _read_attribute attr_name + end end def _read_attribute(attr_name) -- cgit v1.2.3 From bbe0a507f287c20ab4ae8a244fbfc810665deda5 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 15 Apr 2011 01:44:27 +0100 Subject: Remove unnecessary code from define_read_method and add assertion to make sure the underscored version is actually generated --- activerecord/lib/active_record/attribute_methods/read.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record/attribute_methods') diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 43f736c89c..dd3f4699f7 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -70,13 +70,10 @@ 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__) - else - generated_attribute_methods.module_eval do - define_method("_#{symbol}") { eval(access_code) } - alias_method(symbol, "_#{symbol}") - end + + generated_attribute_methods.module_eval do + define_method("_#{attr_name}") { eval(access_code) } + alias_method(attr_name, "_#{attr_name}") end end end -- cgit v1.2.3 From e01dfb27fc5573db9070dce788f2e5ee62094722 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 15 Apr 2011 13:09:12 +0100 Subject: Undo performances regressions I introduced in bbe0a507f287c20ab4ae8a244fbfc810665deda5 and add test for an edge case. Add comments to explain the intent of the code. --- .../lib/active_record/attribute_methods/read.rb | 28 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record/attribute_methods') diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index dd3f4699f7..cd6c4002d2 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}" @@ -71,9 +73,25 @@ module ActiveRecord access_code = "@attributes_cache['#{attr_name}'] ||= (#{access_code})" end - generated_attribute_methods.module_eval do - define_method("_#{attr_name}") { eval(access_code) } - alias_method(attr_name, "_#{attr_name}") + # 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("_#{method_name}") { eval(access_code) } + alias_method(method_name, "_#{method_name}") + end end end end -- cgit v1.2.3 From 65469a6e5e8cd2418c99c3862dd33feed69536bd Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 15 Apr 2011 13:27:08 +0100 Subject: Return nil from read_attribute(:foo) if 'foo' is not present in the @attributes hash, but the _foo method has been defined. This brings the behaviour into line with the 3-0-stable branch and the master branch before 93641ed6c8c684f6b4db02b6c8a22fa9bc7f0eaf (there were previously no assertions about this which is why the change slipped through). Note that actually calling the 'foo' method will still raise an error if the attribute is not present. --- activerecord/lib/active_record/attribute_methods/read.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/attribute_methods') diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index cd6c4002d2..a248eb3a7b 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -100,7 +100,7 @@ module ActiveRecord # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). def read_attribute(attr_name) if respond_to? "_#{attr_name}" - send "_#{attr_name}" + send "_#{attr_name}" if @attributes.has_key?(attr_name.to_s) else _read_attribute attr_name end -- cgit v1.2.3