From af0d1fa8920793a95fae456d1f5debdc50287eb3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@gmail.com>
Date: Wed, 7 Oct 2009 11:17:50 -0300
Subject: Update Orchestra instrumentations and move part of logging to
 Orchestra.

---
 activerecord/lib/active_record/base.rb                     |  2 ++
 .../active_record/connection_adapters/abstract_adapter.rb  | 14 ++++----------
 activerecord/lib/active_record/instrument.rb               |  5 +++++
 3 files changed, 11 insertions(+), 10 deletions(-)
 create mode 100644 activerecord/lib/active_record/instrument.rb

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 283aa7ddfc..eae59dfad7 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1,3 +1,4 @@
+require 'benchmark'
 require 'yaml'
 require 'set'
 require 'active_support/dependencies'
@@ -11,6 +12,7 @@ require 'active_support/core_ext/hash/indifferent_access'
 require 'active_support/core_ext/hash/slice'
 require 'active_support/core_ext/string/behavior'
 require 'active_support/core_ext/symbol'
+require 'active_support/core_ext/benchmark'
 require 'active_support/core_ext/object/metaclass'
 
 module ActiveRecord #:nodoc:
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 694e1e561c..b411fe7526 100755
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -1,4 +1,3 @@
-require 'benchmark'
 require 'date'
 require 'bigdecimal'
 require 'bigdecimal/util'
@@ -12,8 +11,6 @@ require 'active_record/connection_adapters/abstract/connection_pool'
 require 'active_record/connection_adapters/abstract/connection_specification'
 require 'active_record/connection_adapters/abstract/query_cache'
 
-require 'active_support/core_ext/benchmark'
-
 module ActiveRecord
   module ConnectionAdapters # :nodoc:
     # ActiveRecord supports multiple database systems. AbstractAdapter and
@@ -33,6 +30,7 @@ module ActiveRecord
       include Quoting, DatabaseStatements, SchemaStatements
       include QueryCache
       include ActiveSupport::Callbacks
+
       define_callbacks :checkout, :checkin
 
       @@row_even = true
@@ -193,6 +191,7 @@ module ActiveRecord
       end
 
       def log_info(sql, name, ms)
+        @runtime += ms
         if @logger && @logger.debug?
           name = '%s (%.1fms)' % [name || 'SQL', ms]
           @logger.debug(format_log_entry(name, sql.squeeze(' ')))
@@ -200,13 +199,8 @@ module ActiveRecord
       end
 
       protected
-        def log(sql, name)
-          event = ActiveSupport::Orchestra.instrument(:sql, :sql => sql, :name => name) do
-            yield if block_given?
-          end
-          @runtime += event.duration
-          log_info(sql, name, event.duration)
-          event.result
+        def log(sql, name, &block)
+          ActiveSupport::Orchestra.instrument(:sql, :sql => sql, :name => name, &block)
         rescue Exception => e
           # Log message and raise exception.
           # Set last_verification to 0, so that connection gets verified
diff --git a/activerecord/lib/active_record/instrument.rb b/activerecord/lib/active_record/instrument.rb
new file mode 100644
index 0000000000..06d3e40080
--- /dev/null
+++ b/activerecord/lib/active_record/instrument.rb
@@ -0,0 +1,5 @@
+require 'active_support/orchestra'
+
+ActiveSupport::Orchestra.subscribe("sql") do |event|
+  ActiveRecord::Base.connection.log_info(event.payload[:sql], event.payload[:name], event.duration)
+end
-- 
cgit v1.2.3


From a15e02d44ac2afb27a7e8e652c98a796d271b645 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@gmail.com>
Date: Fri, 9 Oct 2009 09:52:25 -0300
Subject: Unify benchmark APIs.

---
 activerecord/lib/active_record/base.rb | 36 +++-------------------------------
 1 file changed, 3 insertions(+), 33 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index eae59dfad7..76dbd00ad9 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1,6 +1,7 @@
 require 'benchmark'
 require 'yaml'
 require 'set'
+require 'active_support/benchmarkable'
 require 'active_support/dependencies'
 require 'active_support/time'
 require 'active_support/core_ext/class/attribute_accessors'
@@ -12,7 +13,6 @@ require 'active_support/core_ext/hash/indifferent_access'
 require 'active_support/core_ext/hash/slice'
 require 'active_support/core_ext/string/behavior'
 require 'active_support/core_ext/symbol'
-require 'active_support/core_ext/benchmark'
 require 'active_support/core_ext/object/metaclass'
 
 module ActiveRecord #:nodoc:
@@ -1465,38 +1465,6 @@ module ActiveRecord #:nodoc:
         connection.quote(object)
       end
 
-      # Log and benchmark multiple statements in a single block. Example:
-      #
-      #   Project.benchmark("Creating project") do
-      #     project = Project.create("name" => "stuff")
-      #     project.create_manager("name" => "David")
-      #     project.milestones << Milestone.find(:all)
-      #   end
-      #
-      # The benchmark is only recorded if the current level of the logger is less than or equal to the <tt>log_level</tt>,
-      # which makes it easy to include benchmarking statements in production software that will remain inexpensive because
-      # the benchmark will only be conducted if the log level is low enough.
-      #
-      # The logging of the multiple statements is turned off unless <tt>use_silence</tt> is set to false.
-      def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
-        if logger && logger.level <= log_level
-          result = nil
-          ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
-          logger.add(log_level, '%s (%.1fms)' % [title, ms])
-          result
-        else
-          yield
-        end
-      end
-
-      # Silences the logger for the duration of the block.
-      def silence
-        old_logger_level, logger.level = logger.level, Logger::ERROR if logger
-        yield
-      ensure
-        logger.level = old_logger_level if logger
-      end
-
       # Overwrite the default class equality method to provide support for association proxies.
       def ===(object)
         object.is_a?(self)
@@ -3155,6 +3123,8 @@ module ActiveRecord #:nodoc:
   Base.class_eval do
     extend ActiveModel::Naming
     extend QueryCache::ClassMethods
+    extend ActiveSupport::Benchmarkable
+
     include Validations
     include Locking::Optimistic, Locking::Pessimistic
     include AttributeMethods
-- 
cgit v1.2.3


From 2d7abe245e7a2b1717e48ef550e4083318fd7ec2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@gmail.com>
Date: Thu, 15 Oct 2009 18:51:51 -0300
Subject: Renamed Orchestra to Notifications once again [#3321 state:resolved]

---
 .../lib/active_record/connection_adapters/abstract_adapter.rb        | 2 +-
 activerecord/lib/active_record/instrument.rb                         | 5 -----
 activerecord/lib/active_record/notifications.rb                      | 5 +++++
 3 files changed, 6 insertions(+), 6 deletions(-)
 delete mode 100644 activerecord/lib/active_record/instrument.rb
 create mode 100644 activerecord/lib/active_record/notifications.rb

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index b411fe7526..8fae26b790 100755
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -200,7 +200,7 @@ module ActiveRecord
 
       protected
         def log(sql, name, &block)
-          ActiveSupport::Orchestra.instrument(:sql, :sql => sql, :name => name, &block)
+          ActiveSupport::Notifications.instrument(:sql, :sql => sql, :name => name, &block)
         rescue Exception => e
           # Log message and raise exception.
           # Set last_verification to 0, so that connection gets verified
diff --git a/activerecord/lib/active_record/instrument.rb b/activerecord/lib/active_record/instrument.rb
deleted file mode 100644
index 06d3e40080..0000000000
--- a/activerecord/lib/active_record/instrument.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'active_support/orchestra'
-
-ActiveSupport::Orchestra.subscribe("sql") do |event|
-  ActiveRecord::Base.connection.log_info(event.payload[:sql], event.payload[:name], event.duration)
-end
diff --git a/activerecord/lib/active_record/notifications.rb b/activerecord/lib/active_record/notifications.rb
new file mode 100644
index 0000000000..a5ce7ac524
--- /dev/null
+++ b/activerecord/lib/active_record/notifications.rb
@@ -0,0 +1,5 @@
+require 'active_support/notifications'
+
+ActiveSupport::Notifications.subscribe("sql") do |event|
+  ActiveRecord::Base.connection.log_info(event.payload[:sql], event.payload[:name], event.duration)
+end
-- 
cgit v1.2.3


From 471a394215e01ffae03bbafa027a44f63e0658b8 Mon Sep 17 00:00:00 2001
From: Nick Sieger <nick@nicksieger.com>
Date: Fri, 16 Oct 2009 11:39:32 -0500
Subject: Modify connection pool callbacks to be compatible w/ new style

Signed-off-by: Yehuda Katz <wycats@gmail.com>
---
 .../connection_adapters/abstract/connection_pool.rb        | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index 12253eac3f..377f2a44c5 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -211,9 +211,10 @@ module ActiveRecord
       # calling +checkout+ on this pool.
       def checkin(conn)
         @connection_mutex.synchronize do
-          conn.run_callbacks :checkin
-          @checked_out.delete conn
-          @queue.signal
+          conn.run_callbacks :checkin do
+            @checked_out.delete conn
+            @queue.signal
+          end
         end
       end
 
@@ -255,9 +256,10 @@ module ActiveRecord
       end
 
       def checkout_and_verify(c)
-        c.verify!
-        c.run_callbacks :checkout
-        @checked_out << c
+        c.run_callbacks :checkout do
+          c.verify!
+          @checked_out << c
+        end
         c
       end
     end
-- 
cgit v1.2.3


From 4cebd41d9e9764b29a5673a298a71b0c530b2bf6 Mon Sep 17 00:00:00 2001
From: Joshua Peek <josh@joshpeek.com>
Date: Fri, 16 Oct 2009 19:08:09 -0500
Subject: Fix Rails root in sqlite adapter

---
 .../lib/active_record/connection_adapters/sqlite_adapter.rb         | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index 5a49fc2d2f..c9c2892ba4 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -11,11 +11,11 @@ module ActiveRecord
             raise ArgumentError, "No database file specified. Missing argument: database"
           end
 
-          # Allow database path relative to RAILS_ROOT, but only if
+          # Allow database path relative to Rails.root, but only if
           # the database path is not the special path that tells
           # Sqlite to build a database only in memory.
-          if Object.const_defined?(:RAILS_ROOT) && ':memory:' != config[:database]
-            config[:database] = File.expand_path(config[:database], RAILS_ROOT)
+          if Object.const_defined?(:Rails) && ':memory:' != config[:database]
+            config[:database] = File.expand_path(config[:database], Rails.root)
           end
         end
     end
-- 
cgit v1.2.3


From f936a1f100e75082081e782e5cceb272885c2df7 Mon Sep 17 00:00:00 2001
From: Eric Chapweske <eric@chapweske.com>
Date: Sat, 17 Oct 2009 12:37:15 -0500
Subject: Refactoring attributes/types [#3348 state:resolved]

Signed-off-by: Joshua Peek <josh@joshpeek.com>
---
 activerecord/lib/active_record.rb                  |  16 +++
 .../attribute_methods/before_type_cast.rb          |  13 +--
 .../lib/active_record/attribute_methods/query.rb   |  20 +---
 .../lib/active_record/attribute_methods/read.rb    |  49 +--------
 .../attribute_methods/time_zone_conversion.rb      |  48 ++-------
 .../lib/active_record/attribute_methods/write.rb   |   9 +-
 activerecord/lib/active_record/attributes.rb       |  37 +++++++
 .../lib/active_record/attributes/aliasing.rb       |  42 ++++++++
 activerecord/lib/active_record/attributes/store.rb |  15 +++
 .../lib/active_record/attributes/typecasting.rb    | 111 +++++++++++++++++++++
 activerecord/lib/active_record/base.rb             |  38 ++-----
 activerecord/lib/active_record/types.rb            |  38 +++++++
 activerecord/lib/active_record/types/number.rb     |  30 ++++++
 activerecord/lib/active_record/types/object.rb     |  37 +++++++
 activerecord/lib/active_record/types/serialize.rb  |  33 ++++++
 .../lib/active_record/types/time_with_zone.rb      |  20 ++++
 activerecord/lib/active_record/types/unknown.rb    |  37 +++++++
 17 files changed, 445 insertions(+), 148 deletions(-)
 create mode 100644 activerecord/lib/active_record/attributes.rb
 create mode 100644 activerecord/lib/active_record/attributes/aliasing.rb
 create mode 100644 activerecord/lib/active_record/attributes/store.rb
 create mode 100644 activerecord/lib/active_record/attributes/typecasting.rb
 create mode 100644 activerecord/lib/active_record/types.rb
 create mode 100644 activerecord/lib/active_record/types/number.rb
 create mode 100644 activerecord/lib/active_record/types/object.rb
 create mode 100644 activerecord/lib/active_record/types/serialize.rb
 create mode 100644 activerecord/lib/active_record/types/time_with_zone.rb
 create mode 100644 activerecord/lib/active_record/types/unknown.rb

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 2d66fa9fcb..8f118a6057 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -51,6 +51,7 @@ module ActiveRecord
   autoload :AssociationPreload, 'active_record/association_preload'
   autoload :Associations, 'active_record/associations'
   autoload :AttributeMethods, 'active_record/attribute_methods'
+  autoload :Attributes, 'active_record/attributes'
   autoload :AutosaveAssociation, 'active_record/autosave_association'
   autoload :Relation, 'active_record/relation'
   autoload :Base, 'active_record/base'
@@ -74,6 +75,7 @@ module ActiveRecord
   autoload :TestCase, 'active_record/test_case'
   autoload :Timestamp, 'active_record/timestamp'
   autoload :Transactions, 'active_record/transactions'
+  autoload :Types, 'active_record/types'
   autoload :Validator, 'active_record/validator'
   autoload :Validations, 'active_record/validations'
 
@@ -87,6 +89,20 @@ module ActiveRecord
     autoload :Write, 'active_record/attribute_methods/write'
   end
 
+  module Attributes
+    autoload :Aliasing, 'active_record/attributes/aliasing'
+    autoload :Store, 'active_record/attributes/store'
+    autoload :Typecasting, 'active_record/attributes/typecasting'
+  end
+
+  module Type
+    autoload :Number, 'active_record/types/number'
+    autoload :Object, 'active_record/types/object'
+    autoload :Serialize, 'active_record/types/serialize'
+    autoload :TimeWithZone, 'active_record/types/time_with_zone'
+    autoload :Unknown, 'active_record/types/unknown'
+  end
+
   module Locking
     autoload :Optimistic, 'active_record/locking/optimistic'
     autoload :Pessimistic, 'active_record/locking/pessimistic'
diff --git a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb
index a4e144f233..74921241f7 100644
--- a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb
+++ b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb
@@ -8,25 +8,18 @@ module ActiveRecord
       end
 
       def read_attribute_before_type_cast(attr_name)
-        @attributes[attr_name]
+        _attributes.without_typecast[attr_name]
       end
 
       # Returns a hash of attributes before typecasting and deserialization.
       def attributes_before_type_cast
-        self.attribute_names.inject({}) do |attrs, name|
-          attrs[name] = read_attribute_before_type_cast(name)
-          attrs
-        end
+        _attributes.without_typecast
       end
 
       private
         # Handle *_before_type_cast for method_missing.
         def attribute_before_type_cast(attribute_name)
-          if attribute_name == 'id'
-            read_attribute_before_type_cast(self.class.primary_key)
-          else
-            read_attribute_before_type_cast(attribute_name)
-          end
+          read_attribute_before_type_cast(attribute_name)
         end
     end
   end
diff --git a/activerecord/lib/active_record/attribute_methods/query.rb b/activerecord/lib/active_record/attribute_methods/query.rb
index a949d80120..0154ee35f8 100644
--- a/activerecord/lib/active_record/attribute_methods/query.rb
+++ b/activerecord/lib/active_record/attribute_methods/query.rb
@@ -8,23 +8,7 @@ module ActiveRecord
       end
 
       def query_attribute(attr_name)
-        unless value = read_attribute(attr_name)
-          false
-        else
-          column = self.class.columns_hash[attr_name]
-          if column.nil?
-            if Numeric === value || value !~ /[^0-9]/
-              !value.to_i.zero?
-            else
-              return false if ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value)
-              !value.blank?
-            end
-          elsif column.number?
-            !value.zero?
-          else
-            !value.blank?
-          end
-        end
+        _attributes.has?(attr_name)
       end
 
       private
@@ -35,3 +19,5 @@ module ActiveRecord
     end
   end
 end
+
+
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index 3da3d9d8cc..97caec7744 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -37,11 +37,7 @@ module ActiveRecord
 
         protected
           def define_method_attribute(attr_name)
-            if self.serialized_attributes[attr_name]
-              define_read_method_for_serialized_attribute(attr_name)
-            else
-              define_read_method(attr_name.to_sym, attr_name, columns_hash[attr_name])
-            end
+            define_read_method(attr_name.to_sym, attr_name, columns_hash[attr_name])
 
             if attr_name == primary_key && attr_name != "id"
               define_read_method(:id, attr_name, columns_hash[attr_name])
@@ -49,18 +45,12 @@ module ActiveRecord
           end
 
         private
-          # Define read method for serialized attribute.
-          def define_read_method_for_serialized_attribute(attr_name)
-            generated_attribute_methods.module_eval("def #{attr_name}; unserialize_attribute('#{attr_name}'); end", __FILE__, __LINE__)
-          end
 
           # Define an attribute reader method.  Cope with nil column.
           def define_read_method(symbol, attr_name, column)
-            cast_code = column.type_cast_code('v') if column
-            access_code = cast_code ? "(v=@attributes['#{attr_name}']) && #{cast_code}" : "@attributes['#{attr_name}']"
-
+            access_code = "_attributes['#{attr_name}']"
             unless attr_name.to_s == self.primary_key.to_s
-              access_code = access_code.insert(0, "missing_attribute('#{attr_name}', caller) unless @attributes.has_key?('#{attr_name}'); ")
+              access_code = access_code.insert(0, "missing_attribute('#{attr_name}', caller) unless _attributes.key?('#{attr_name}'); ")
             end
 
             if cache_attribute?(attr_name)
@@ -73,38 +63,7 @@ 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)
-        attr_name = attr_name.to_s
-        attr_name = self.class.primary_key if attr_name == 'id'
-        if !(value = @attributes[attr_name]).nil?
-          if column = column_for_attribute(attr_name)
-            if unserializable_attribute?(attr_name, column)
-              unserialize_attribute(attr_name)
-            else
-              column.type_cast(value)
-            end
-          else
-            value
-          end
-        else
-          nil
-        end
-      end
-
-      # Returns true if the attribute is of a text column and marked for serialization.
-      def unserializable_attribute?(attr_name, column)
-        column.text? && self.class.serialized_attributes[attr_name]
-      end
-
-      # Returns the unserialized object of the attribute.
-      def unserialize_attribute(attr_name)
-        unserialized_object = object_from_yaml(@attributes[attr_name])
-
-        if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) || unserialized_object.nil?
-          @attributes.frozen? ? unserialized_object : @attributes[attr_name] = unserialized_object
-        else
-          raise SerializationTypeMismatch,
-            "#{attr_name} was supposed to be a #{self.class.serialized_attributes[attr_name]}, but was a #{unserialized_object.class.to_s}"
-        end
+        _attributes[attr_name]
       end
 
       private
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 a8e3e28a7a..4ac0c7f608 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -12,48 +12,20 @@ module ActiveRecord
       end
 
       module ClassMethods
+
+        def cache_attribute?(attr_name)
+          time_zone_aware?(attr_name) || super
+        end
+
         protected
-          # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled.
-          # This enhanced read method automatically converts the UTC time stored in the database to the time zone stored in Time.zone.
-          def define_method_attribute(attr_name)
-            if create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
-              method_body = <<-EOV
-                def #{attr_name}(reload = false)
-                  cached = @attributes_cache['#{attr_name}']
-                  return cached if cached && !reload
-                  time = read_attribute('#{attr_name}')
-                  @attributes_cache['#{attr_name}'] = time.acts_like?(:time) ? time.in_time_zone : time
-                end
-              EOV
-              generated_attribute_methods.module_eval(method_body, __FILE__, __LINE__)
-            else
-              super
-            end
-          end
 
-          # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled.
-          # This enhanced write method will automatically convert the time passed to it to the zone stored in Time.zone.
-          def define_method_attribute=(attr_name)
-            if create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name])
-              method_body = <<-EOV
-                def #{attr_name}=(time)
-                  unless time.acts_like?(:time)
-                    time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time
-                  end
-                  time = time.in_time_zone rescue nil if time
-                  write_attribute(:#{attr_name}, time)
-                end
-              EOV
-              generated_attribute_methods.module_eval(method_body, __FILE__, __LINE__)
-            else
-              super
-            end
+          def time_zone_aware?(attr_name)
+            column = columns_hash[attr_name]
+            time_zone_aware_attributes &&
+              !skip_time_zone_conversion_for_attributes.include?(attr_name.to_sym) &&
+                [:datetime, :timestamp].include?(column.type)
           end
 
-        private
-          def create_time_zone_conversion_attribute?(name, column)
-            time_zone_aware_attributes && !skip_time_zone_conversion_for_attributes.include?(name.to_sym) && [:datetime, :timestamp].include?(column.type)
-          end
       end
     end
   end
diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb
index e31acac050..37eadbe0a9 100644
--- a/activerecord/lib/active_record/attribute_methods/write.rb
+++ b/activerecord/lib/active_record/attribute_methods/write.rb
@@ -17,14 +17,9 @@ module ActiveRecord
       # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float
       # columns are turned into +nil+.
       def write_attribute(attr_name, value)
-        attr_name = attr_name.to_s
-        attr_name = self.class.primary_key if attr_name == 'id'
+        attr_name = _attributes.unalias(attr_name)
         @attributes_cache.delete(attr_name)
-        if (column = column_for_attribute(attr_name)) && column.number?
-          @attributes[attr_name] = convert_number_column_value(value)
-        else
-          @attributes[attr_name] = value
-        end
+        _attributes[attr_name] = value
       end
 
       private
diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb
new file mode 100644
index 0000000000..e4d9e89821
--- /dev/null
+++ b/activerecord/lib/active_record/attributes.rb
@@ -0,0 +1,37 @@
+module ActiveRecord
+  module Attributes
+
+     # Returns true if the given attribute is in the attributes hash
+     def has_attribute?(attr_name)
+       _attributes.key?(attr_name)
+     end
+
+     # Returns an array of names for the attributes available on this object sorted alphabetically.
+     def attribute_names
+       _attributes.keys.sort!
+     end
+
+     # Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
+     def attributes
+       attributes = _attributes.dup
+       attributes.typecast! unless _attributes.frozen?
+       attributes.to_h
+     end
+
+     protected
+
+     # Not to be confused with the public #attributes method, which returns a typecasted Hash.
+     def _attributes
+       @attributes
+     end
+
+     def initialize_attribute_store(merge_attributes = nil)
+       @attributes = ActiveRecord::Attributes::Store.new
+       @attributes.merge!(merge_attributes) if merge_attributes
+       @attributes.types.merge!(self.class.attribute_types)
+       @attributes.aliases.merge!('id' => self.class.primary_key) unless 'id' == self.class.primary_key
+       @attributes
+     end
+
+  end
+end
diff --git a/activerecord/lib/active_record/attributes/aliasing.rb b/activerecord/lib/active_record/attributes/aliasing.rb
new file mode 100644
index 0000000000..db77739d1f
--- /dev/null
+++ b/activerecord/lib/active_record/attributes/aliasing.rb
@@ -0,0 +1,42 @@
+module ActiveRecord
+  module Attributes
+    module Aliasing
+      # Allows access to keys using aliased names.
+      #
+      # Example:
+      # class Attributes < Hash
+      #   include Aliasing
+      # end
+      #
+      # attributes = Attributes.new
+      # attributes.aliases['id'] = 'fancy_primary_key'
+      # attributes['fancy_primary_key'] = 2020
+      #
+      # attributes['id']
+      # => 2020
+      #
+      # Additionally, symbols are always aliases of strings:
+      # attributes[:fancy_primary_key]
+      # => 2020
+      #
+      def [](key)
+        super(unalias(key))
+      end
+
+      def []=(key, value)
+        super(unalias(key), value)
+      end
+
+      def aliases
+        @aliases ||= {}
+      end
+
+      def unalias(key)
+        key = key.to_s
+        aliases[key] || key
+      end
+
+    end
+  end
+end
+
diff --git a/activerecord/lib/active_record/attributes/store.rb b/activerecord/lib/active_record/attributes/store.rb
new file mode 100644
index 0000000000..61109f4acc
--- /dev/null
+++ b/activerecord/lib/active_record/attributes/store.rb
@@ -0,0 +1,15 @@
+module ActiveRecord
+  module Attributes
+    class Store < Hash
+      include ActiveRecord::Attributes::Typecasting
+      include ActiveRecord::Attributes::Aliasing
+
+      # Attributes not mapped to a column are handled using Type::Unknown,
+      # which enables boolean typecasting for unmapped keys.
+      def types
+        @types ||= Hash.new(Type::Unknown.new)
+      end
+
+    end
+  end
+end
diff --git a/activerecord/lib/active_record/attributes/typecasting.rb b/activerecord/lib/active_record/attributes/typecasting.rb
new file mode 100644
index 0000000000..de36a297eb
--- /dev/null
+++ b/activerecord/lib/active_record/attributes/typecasting.rb
@@ -0,0 +1,111 @@
+module ActiveRecord
+  module Attributes
+    module Typecasting
+      # Typecasts values during access based on their key mapping to a Type.
+      #
+      # Example:
+      # class Attributes < Hash
+      #   include Typecasting
+      # end
+      #
+      # attributes = Attributes.new
+      # attributes.types['comments_count'] = Type::Integer
+      # attributes['comments_count'] = '5'
+      #
+      # attributes['comments_count']
+      # => 5
+      #
+      # To support keys not mapped to a typecaster, add a default to types.
+      # attributes.types.default = Type::Unknown
+      # attributes['age'] = '25'
+      # attributes['age']
+      # => '25'
+      #
+      # A valid type supports #cast, #precast, #boolean, and #appendable? methods.
+      #
+      def [](key)
+        value = super(key)
+        typecast_read(key, value)
+      end
+
+      def []=(key, value)
+        super(key, typecast_write(key, value))
+      end
+
+      def to_h
+        hash = {}
+        hash.merge!(self)
+        hash
+      end
+
+      # Provides a duplicate with typecasting disabled.
+      #
+      # Example:
+      # attributes = Attributes.new
+      # attributes.types['comments_count'] = Type::Integer
+      # attributes['comments_count'] = '5'
+      #
+      # attributes.without_typecast['comments_count']
+      # => '5'
+      #
+      def without_typecast
+        dup.without_typecast!
+      end
+
+      def without_typecast!
+        types.clear
+        self
+      end
+
+      def typecast!
+        keys.each { |key| self[key] = self[key] }
+        self
+      end
+
+      # Check if key has a value that typecasts to true.
+      #
+      # attributes = Attributes.new
+      # attributes.types['comments_count'] = Type::Integer
+      #
+      # attributes['comments_count'] = 0
+      # attributes.has?('comments_count')
+      # => false
+      #
+      # attributes['comments_count'] = 1
+      # attributes.has?('comments_count')
+      # => true
+      #
+      def has?(key)
+        value = self[key]
+        boolean_typecast(key, value)
+      end
+
+      def types
+        @types ||= {}
+      end
+
+      protected
+
+      def types=(other_types)
+        @types = other_types
+      end
+
+      def boolean_typecast(key, value)
+        value ? types[key].boolean(value) : false
+      end
+
+      def typecast_read(key, value)
+        type  = types[key]
+        value = type.cast(value)
+        self[key] = value if type.appendable? && !frozen?
+
+        value
+      end
+
+      def typecast_write(key, value)
+        types[key].precast(value)
+      end
+
+    end
+  end
+end
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 76dbd00ad9..4274df54cc 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1644,7 +1644,7 @@ module ActiveRecord #:nodoc:
         def instantiate(record)
           object = find_sti_class(record[inheritance_column]).allocate
 
-          object.instance_variable_set(:'@attributes', record)
+          object.send(:initialize_attribute_store, record)
           object.instance_variable_set(:'@attributes_cache', {})
 
           object.send(:_run_find_callbacks)
@@ -2415,7 +2415,7 @@ module ActiveRecord #:nodoc:
       # In both instances, valid attribute keys are determined by the column names of the associated table --
       # hence you can't have attributes that aren't part of the table columns.
       def initialize(attributes = nil)
-        @attributes = attributes_from_column_definition
+        initialize_attribute_store(attributes_from_column_definition)
         @attributes_cache = {}
         @new_record = true
         ensure_proper_type
@@ -2441,7 +2441,7 @@ module ActiveRecord #:nodoc:
         callback(:after_initialize) if respond_to_without_attributes?(:after_initialize)
         cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
         cloned_attributes.delete(self.class.primary_key)
-        @attributes = cloned_attributes
+        initialize_attribute_store(cloned_attributes)
         clear_aggregation_cache
         @attributes_cache = {}
         @new_record = true
@@ -2667,7 +2667,7 @@ module ActiveRecord #:nodoc:
       def reload(options = nil)
         clear_aggregation_cache
         clear_association_cache
-        @attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes'))
+        _attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes'))
         @attributes_cache = {}
         self
       end
@@ -2764,16 +2764,6 @@ module ActiveRecord #:nodoc:
         !value.blank?
       end
 
-      # Returns true if the given attribute is in the attributes hash
-      def has_attribute?(attr_name)
-        @attributes.has_key?(attr_name.to_s)
-      end
-
-      # Returns an array of names for the attributes available on this object sorted alphabetically.
-      def attribute_names
-        @attributes.keys.sort
-      end
-
       # Returns the column object for the named attribute.
       def column_for_attribute(name)
         self.class.columns_hash[name.to_s]
@@ -2897,18 +2887,6 @@ module ActiveRecord #:nodoc:
         end
       end
 
-      def convert_number_column_value(value)
-        if value == false
-          0
-        elsif value == true
-          1
-        elsif value.is_a?(String) && value.blank?
-          nil
-        else
-          value
-        end
-      end
-
       def remove_attributes_protected_from_mass_assignment(attributes)
         safe_attributes =
           if self.class.accessible_attributes.nil? && self.class.protected_attributes.nil?
@@ -3027,7 +3005,7 @@ module ActiveRecord #:nodoc:
       end
 
       def instantiate_time_object(name, values)
-        if self.class.send(:create_time_zone_conversion_attribute?, name, column_for_attribute(name))
+        if self.class.send(:time_zone_aware?, name)
           Time.zone.local(*values)
         else
           Time.time_with_datetime_fallback(@@default_timezone, *values)
@@ -3114,10 +3092,6 @@ module ActiveRecord #:nodoc:
         comma_pair_list(quote_columns(quoter, hash))
       end
 
-      def object_from_yaml(string)
-        return string unless string.is_a?(String) && string =~ /^---/
-        YAML::load(string) rescue string
-      end
   end
 
   Base.class_eval do
@@ -3132,6 +3106,7 @@ module ActiveRecord #:nodoc:
     include AttributeMethods::PrimaryKey
     include AttributeMethods::TimeZoneConversion
     include AttributeMethods::Dirty
+    include Attributes, Types
     include Callbacks, ActiveModel::Observing, Timestamp
     include Associations, AssociationPreload, NamedScope
     include ActiveModel::Conversion
@@ -3141,6 +3116,7 @@ module ActiveRecord #:nodoc:
     include AutosaveAssociation, NestedAttributes
 
     include Aggregations, Transactions, Reflection, Batches, Calculations, Serialization
+
   end
 end
 
diff --git a/activerecord/lib/active_record/types.rb b/activerecord/lib/active_record/types.rb
new file mode 100644
index 0000000000..74f569352b
--- /dev/null
+++ b/activerecord/lib/active_record/types.rb
@@ -0,0 +1,38 @@
+module ActiveRecord
+  module Types
+    extend ActiveSupport::Concern
+
+    module ClassMethods
+
+      def attribute_types
+        attribute_types = {}
+        columns.each do |column|
+          options = {}
+          options[:time_zone_aware] = time_zone_aware?(column.name)
+          options[:serialize]       = serialized_attributes[column.name]
+
+          attribute_types[column.name] = to_type(column, options)
+        end
+        attribute_types
+      end
+
+      private
+
+      def to_type(column, options = {})
+        type_class = if options[:time_zone_aware]
+          Type::TimeWithZone
+        elsif options[:serialize]
+          Type::Serialize
+        elsif [ :integer, :float, :decimal ].include?(column.type)
+          Type::Number
+        else
+          Type::Object
+        end
+
+        type_class.new(column, options)
+      end
+
+    end
+
+  end
+end
diff --git a/activerecord/lib/active_record/types/number.rb b/activerecord/lib/active_record/types/number.rb
new file mode 100644
index 0000000000..cfbe877575
--- /dev/null
+++ b/activerecord/lib/active_record/types/number.rb
@@ -0,0 +1,30 @@
+module ActiveRecord
+  module Type
+    class Number < Object
+
+      def boolean(value)
+        value = cast(value)
+        !(value.nil? || value.zero?)
+      end
+
+      def precast(value)
+        convert_number_column_value(value)
+      end
+
+      private
+
+      def convert_number_column_value(value)
+        if value == false
+          0
+        elsif value == true
+          1
+        elsif value.is_a?(String) && value.blank?
+          nil
+        else
+          value
+        end
+      end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/activerecord/lib/active_record/types/object.rb b/activerecord/lib/active_record/types/object.rb
new file mode 100644
index 0000000000..ec3f861abd
--- /dev/null
+++ b/activerecord/lib/active_record/types/object.rb
@@ -0,0 +1,37 @@
+module ActiveRecord
+  module Type
+    module Casting
+
+       def cast(value)
+         typecaster.type_cast(value)
+       end
+
+       def precast(value)
+         value
+       end
+
+       def boolean(value)
+         cast(value).present?
+       end
+
+       # Attributes::Typecasting stores appendable? types (e.g. serialized Arrays) when typecasting reads.
+       def appendable?
+         false
+       end
+
+    end
+
+    class Object
+      include Casting
+
+      attr_reader :name, :options
+      attr_reader :typecaster
+
+      def initialize(typecaster = nil, options = {})
+        @typecaster, @options = typecaster, options
+      end
+
+    end
+
+  end
+end
\ No newline at end of file
diff --git a/activerecord/lib/active_record/types/serialize.rb b/activerecord/lib/active_record/types/serialize.rb
new file mode 100644
index 0000000000..7b6af1981f
--- /dev/null
+++ b/activerecord/lib/active_record/types/serialize.rb
@@ -0,0 +1,33 @@
+module ActiveRecord
+  module Type
+    class Serialize < Object
+
+      def cast(value)
+        unserialize(value)
+      end
+
+      def appendable?
+        true
+      end
+
+      protected
+
+      def unserialize(value)
+        unserialized_object = object_from_yaml(value)
+
+        if unserialized_object.is_a?(@options[:serialize]) || unserialized_object.nil?
+          unserialized_object
+        else
+          raise SerializationTypeMismatch,
+            "#{name} was supposed to be a #{@options[:serialize]}, but was a #{unserialized_object.class.to_s}"
+        end
+      end
+
+      def object_from_yaml(string)
+        return string unless string.is_a?(String) && string =~ /^---/
+        YAML::load(string) rescue string
+      end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/activerecord/lib/active_record/types/time_with_zone.rb b/activerecord/lib/active_record/types/time_with_zone.rb
new file mode 100644
index 0000000000..3a8b9292f9
--- /dev/null
+++ b/activerecord/lib/active_record/types/time_with_zone.rb
@@ -0,0 +1,20 @@
+module ActiveRecord
+  module Type
+    class TimeWithZone < Object
+
+      def cast(time)
+        time = super(time)
+        time.acts_like?(:time) ? time.in_time_zone : time
+      end
+
+      def precast(time)
+        unless time.acts_like?(:time)
+          time = time.is_a?(String) ? ::Time.zone.parse(time) : time.to_time rescue time
+        end
+        time = time.in_time_zone rescue nil if time
+        super(time)
+      end
+
+    end
+  end
+end
diff --git a/activerecord/lib/active_record/types/unknown.rb b/activerecord/lib/active_record/types/unknown.rb
new file mode 100644
index 0000000000..f832c7b304
--- /dev/null
+++ b/activerecord/lib/active_record/types/unknown.rb
@@ -0,0 +1,37 @@
+module ActiveRecord
+  module Type
+    # Useful for handling attributes not mapped to types. Performs some boolean typecasting,
+    # but otherwise leaves the value untouched.
+    class Unknown
+
+      def cast(value)
+        value
+      end
+
+      def precast(value)
+        value
+      end
+
+      # Attempts typecasting to handle numeric, false and blank values.
+      def boolean(value)
+        empty = (numeric?(value) && value.to_i.zero?) || false?(value) || value.blank?
+        !empty
+      end
+
+      def appendable?
+        false
+      end
+
+      protected
+
+      def false?(value)
+        ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value)
+      end
+
+      def numeric?(value)
+        Numeric === value || value !~ /[^0-9]/
+      end
+
+    end
+  end
+end
\ No newline at end of file
-- 
cgit v1.2.3


From 2831996483c6a045f1f38d8030256eb58d9771c3 Mon Sep 17 00:00:00 2001
From: Eric Chapweske <eric@chapweske.com>
Date: Sun, 18 Oct 2009 10:22:22 -0500
Subject: Fixed: #without_typecast should only disable typecasting on the
 duplicated attributes [#3387 state:resolved]

Signed-off-by: Joshua Peek <josh@joshpeek.com>
---
 activerecord/lib/active_record/attributes/typecasting.rb | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/attributes/typecasting.rb b/activerecord/lib/active_record/attributes/typecasting.rb
index de36a297eb..56c32f9895 100644
--- a/activerecord/lib/active_record/attributes/typecasting.rb
+++ b/activerecord/lib/active_record/attributes/typecasting.rb
@@ -37,6 +37,12 @@ module ActiveRecord
         hash.merge!(self)
         hash
       end
+      
+      def dup # :nodoc:
+        copy = super
+        copy.types = types.dup
+        copy
+      end
 
       # Provides a duplicate with typecasting disabled.
       #
-- 
cgit v1.2.3


From 27670363926ee341078aa69ae27204d7338037f5 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper <jeremy@bitsweat.net>
Date: Mon, 19 Oct 2009 19:00:48 -0700
Subject: Use bundled env for tests only

---
 activerecord/lib/active_record.rb | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 8f118a6057..88becfb482 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -21,16 +21,11 @@
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #++
 
-bundled = "#{File.dirname(__FILE__)}/../vendor/gems/environment"
-if File.exist?("#{bundled}.rb")
-  require bundled
-else
-  activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
-  $:.unshift(activesupport_path) if File.directory?(activesupport_path)
+activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
+$:.unshift(activesupport_path) if File.directory?(activesupport_path)
 
-  activemodel_path = "#{File.dirname(__FILE__)}/../../activemodel/lib"
-  $:.unshift(activemodel_path) if File.directory?(activemodel_path)
-end
+activemodel_path = "#{File.dirname(__FILE__)}/../../activemodel/lib"
+$:.unshift(activemodel_path) if File.directory?(activemodel_path)
 
 require 'active_support'
 require 'active_model'
-- 
cgit v1.2.3


From e714b499cc1f7ebc84f8d0e96607b79e60f2828d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@gmail.com>
Date: Tue, 20 Oct 2009 22:20:01 -0200
Subject: Move validator, human_name and human_attribute_name to ActiveModel,
 remove deprecated error messages and add i18n_scope and lookup_ancestors.

Signed-off-by: Carl Lerche <carllerche@mac.com>
---
 activerecord/lib/active_record.rb             |  1 -
 activerecord/lib/active_record/base.rb        | 32 ++--------
 activerecord/lib/active_record/validations.rb | 89 ---------------------------
 activerecord/lib/active_record/validator.rb   | 68 --------------------
 4 files changed, 5 insertions(+), 185 deletions(-)
 delete mode 100644 activerecord/lib/active_record/validator.rb

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 88becfb482..8195e78826 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -71,7 +71,6 @@ module ActiveRecord
   autoload :Timestamp, 'active_record/timestamp'
   autoload :Transactions, 'active_record/transactions'
   autoload :Types, 'active_record/types'
-  autoload :Validator, 'active_record/validator'
   autoload :Validations, 'active_record/validations'
 
   module AttributeMethods
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 4274df54cc..4e6090458a 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1386,7 +1386,8 @@ module ActiveRecord #:nodoc:
         subclasses.each { |klass| klass.reset_inheritable_attributes; klass.reset_column_information }
       end
 
-      def self_and_descendants_from_active_record#nodoc:
+      # Set the lookup ancestors for ActiveModel.
+      def lookup_ancestors #:nodoc:
         klass = self
         classes = [klass]
         while klass != klass.base_class
@@ -1400,32 +1401,9 @@ module ActiveRecord #:nodoc:
         [self]
       end
 
-      # Transforms attribute key names into a more humane format, such as "First name" instead of "first_name". Example:
-      #   Person.human_attribute_name("first_name") # => "First name"
-      # This used to be deprecated in favor of humanize, but is now preferred, because it automatically uses the I18n
-      # module now.
-      # Specify +options+ with additional translating options.
-      def human_attribute_name(attribute_key_name, options = {})
-        defaults = self_and_descendants_from_active_record.map do |klass|
-          :"#{klass.name.underscore}.#{attribute_key_name}"
-        end
-        defaults << options[:default] if options[:default]
-        defaults.flatten!
-        defaults << attribute_key_name.to_s.humanize
-        options[:count] ||= 1
-        I18n.translate(defaults.shift, options.merge(:default => defaults, :scope => [:activerecord, :attributes]))
-      end
-
-      # Transform the modelname into a more humane format, using I18n.
-      # By default, it will underscore then humanize the class name (BlogPost.human_name #=> "Blog post").
-      # Default scope of the translation is activerecord.models
-      # Specify +options+ with additional translating options.
-      def human_name(options = {})
-        defaults = self_and_descendants_from_active_record.map do |klass|
-          :"#{klass.name.underscore}"
-        end
-        defaults << self.name.underscore.humanize
-        I18n.translate(defaults.shift, {:scope => [:activerecord, :models], :count => 1, :default => defaults}.merge(options))
+      # Set the i18n scope to overwrite ActiveModel.
+      def i18n_scope #:nodoc:
+        :activerecord
       end
 
       # True if this isn't a concrete subclass needing a STI type condition.
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index e61b253192..0365cb592f 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -17,90 +17,6 @@ module ActiveRecord
     end
   end
 
-  class Errors < ActiveModel::Errors
-    class << self
-      def default_error_messages
-        message = "Errors.default_error_messages has been deprecated. Please use I18n.translate('activerecord.errors.messages')."
-        ActiveSupport::Deprecation.warn(message)
-
-        I18n.translate 'activerecord.errors.messages'
-      end
-    end
-
-    # Returns all the full error messages in an array.
-    #
-    #   class Company < ActiveRecord::Base
-    #     validates_presence_of :name, :address, :email
-    #     validates_length_of :name, :in => 5..30
-    #   end
-    #
-    #   company = Company.create(:address => '123 First St.')
-    #   company.errors.full_messages # =>
-    #     ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Address can't be blank"]
-    def full_messages(options = {})
-      full_messages = []
-
-      each do |attribute, messages|
-        messages = Array.wrap(messages)
-        next if messages.empty?
-
-        if attribute == :base
-          messages.each {|m| full_messages << m }
-        else
-          attr_name = @base.class.human_attribute_name(attribute.to_s)
-          prefix = attr_name + I18n.t('activerecord.errors.format.separator', :default => ' ')
-          messages.each do |m|
-            full_messages <<  "#{prefix}#{m}"
-          end
-        end
-      end
-
-      full_messages
-    end
-
-    # Translates an error message in it's default scope (<tt>activerecord.errrors.messages</tt>).
-    # Error messages are first looked up in <tt>models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>, if it's not there,
-    # it's looked up in <tt>models.MODEL.MESSAGE</tt> and if that is not there it returns the translation of the
-    # default message (e.g. <tt>activerecord.errors.messages.MESSAGE</tt>). The translated model name,
-    # translated attribute name and the value are available for interpolation.
-    #
-    # When using inheritance in your models, it will check all the inherited models too, but only if the model itself
-    # hasn't been found. Say you have <tt>class Admin < User; end</tt> and you wanted the translation for the <tt>:blank</tt>
-    # error +message+ for the <tt>title</tt> +attribute+, it looks for these translations:
-    #
-    # <ol>
-    # <li><tt>activerecord.errors.models.admin.attributes.title.blank</tt></li>
-    # <li><tt>activerecord.errors.models.admin.blank</tt></li>
-    # <li><tt>activerecord.errors.models.user.attributes.title.blank</tt></li>
-    # <li><tt>activerecord.errors.models.user.blank</tt></li>
-    # <li><tt>activerecord.errors.messages.blank</tt></li>
-    # <li>any default you provided through the +options+ hash (in the activerecord.errors scope)</li>
-    # </ol>
-    def generate_message(attribute, message = :invalid, options = {})
-      message, options[:default] = options[:default], message if options[:default].is_a?(Symbol)
-
-      defaults = @base.class.self_and_descendants_from_active_record.map do |klass|
-        [ :"models.#{klass.name.underscore}.attributes.#{attribute}.#{message}",
-          :"models.#{klass.name.underscore}.#{message}" ]
-      end
-
-      defaults << options.delete(:default)
-      defaults = defaults.compact.flatten << :"messages.#{message}"
-
-      key = defaults.shift
-      value = @base.respond_to?(attribute) ? @base.send(attribute) : nil
-
-      options = { :default => defaults,
-        :model => @base.class.human_name,
-        :attribute => @base.class.human_attribute_name(attribute.to_s),
-        :value => value,
-        :scope => [:activerecord, :errors]
-      }.merge(options)
-
-      I18n.translate(key, options)
-    end
-  end
-
   module Validations
     extend ActiveSupport::Concern
 
@@ -165,11 +81,6 @@ module ActiveRecord
 
         errors.empty?
       end
-
-      # Returns the Errors object that holds all information about attribute error messages.
-      def errors
-        @errors ||= Errors.new(self)
-      end
     end
   end
 end
diff --git a/activerecord/lib/active_record/validator.rb b/activerecord/lib/active_record/validator.rb
deleted file mode 100644
index 83a33f4dcd..0000000000
--- a/activerecord/lib/active_record/validator.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-module ActiveRecord #:nodoc:
-
-  # A simple base class that can be used along with ActiveRecord::Base.validates_with
-  #
-  #   class Person < ActiveRecord::Base
-  #     validates_with MyValidator
-  #   end
-  #
-  #   class MyValidator < ActiveRecord::Validator
-  #     def validate
-  #       if some_complex_logic
-  #         record.errors[:base] = "This record is invalid"
-  #       end
-  #     end
-  #
-  #     private
-  #       def some_complex_logic
-  #         # ...
-  #       end
-  #   end
-  #
-  # Any class that inherits from ActiveRecord::Validator will have access to <tt>record</tt>,
-  # which is an instance of the record being validated, and must implement a method called <tt>validate</tt>.
-  #
-  #   class Person < ActiveRecord::Base
-  #     validates_with MyValidator
-  #   end
-  #
-  #   class MyValidator < ActiveRecord::Validator
-  #     def validate
-  #       record # => The person instance being validated
-  #       options # => Any non-standard options passed to validates_with
-  #     end
-  #   end
-  #
-  # To cause a validation error, you must add to the <tt>record<tt>'s errors directly
-  # from within the validators message
-  #
-  #   class MyValidator < ActiveRecord::Validator
-  #     def validate
-  #       record.errors[:base] << "This is some custom error message"
-  #       record.errors[:first_name] << "This is some complex validation"
-  #       # etc...
-  #     end
-  #   end
-  #
-  # To add behavior to the initialize method, use the following signature:
-  #
-  #   class MyValidator < ActiveRecord::Validator
-  #     def initialize(record, options)
-  #       super
-  #       @my_custom_field = options[:field_name] || :first_name
-  #     end
-  #   end
-  #
-  class Validator
-    attr_reader :record, :options
-
-    def initialize(record, options)
-      @record = record
-      @options = options
-    end
-
-    def validate
-      raise "You must override this method"
-    end
-  end
-end
-- 
cgit v1.2.3