From 218105f58e30bc9487ad59fa455878c35262a0a5 Mon Sep 17 00:00:00 2001
From: Sean Griffin <sean@thoughtbot.com>
Date: Mon, 16 Jun 2014 11:20:55 -0600
Subject: Refactor in-place dirty checking to use the attribute object

---
 activerecord/lib/active_record/attribute.rb           | 19 +++++++++++++++++++
 .../lib/active_record/attribute_methods/dirty.rb      | 12 +++---------
 .../lib/active_record/attribute_methods/read.rb       |  4 ++++
 3 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/activerecord/lib/active_record/attribute.rb b/activerecord/lib/active_record/attribute.rb
index f78cde23c5..8604ccb90d 100644
--- a/activerecord/lib/active_record/attribute.rb
+++ b/activerecord/lib/active_record/attribute.rb
@@ -29,6 +29,14 @@ module ActiveRecord
       type.type_cast_for_database(value)
     end
 
+    def changed_from?(old_value)
+      type.changed?(old_value, value, value_before_type_cast)
+    end
+
+    def changed_in_place_from?(old_value)
+      type.changed_in_place?(old_value, value)
+    end
+
     def type_cast
       raise NotImplementedError
     end
@@ -52,5 +60,16 @@ module ActiveRecord
         type.type_cast_from_user(value)
       end
     end
+
+    class Null
+      class << self
+        attr_reader :value, :value_before_type_cast, :value_for_database
+
+        def changed_from?(*)
+          false
+        end
+        alias changed_in_place_from? changed_from?
+      end
+    end
   end
 end
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index 6a5c057384..9d1310b576 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -137,9 +137,7 @@ module ActiveRecord
       end
 
       def _field_changed?(attr, old_value)
-        new_value = read_attribute(attr)
-        raw_value = read_attribute_before_type_cast(attr)
-        column_for_attribute(attr).changed?(old_value, new_value, raw_value)
+        attribute_named(attr).changed_from?(old_value)
       end
 
       def changed_in_place
@@ -149,10 +147,8 @@ module ActiveRecord
       end
 
       def changed_in_place?(attr_name)
-        type = type_for_attribute(attr_name)
         old_value = original_raw_attribute(attr_name)
-        value = read_attribute(attr_name)
-        type.changed_in_place?(old_value, value)
+        attribute_named(attr_name).changed_in_place_from?(old_value)
       end
 
       def original_raw_attribute(attr_name)
@@ -166,9 +162,7 @@ module ActiveRecord
       end
 
       def store_original_raw_attribute(attr_name)
-        type = type_for_attribute(attr_name)
-        value = type.type_cast_for_database(read_attribute(attr_name))
-        original_raw_attributes[attr_name] = value
+        original_raw_attributes[attr_name] = attribute_named(attr_name).value_for_database
       end
 
       def store_original_raw_attributes
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index 8c1cc128f7..525c46970a 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -99,6 +99,10 @@ module ActiveRecord
       def attribute(attribute_name)
         read_attribute(attribute_name)
       end
+
+      def attribute_named(attribute_name)
+        @attributes.fetch(attribute_name, Attribute::Null)
+      end
     end
   end
 end
-- 
cgit v1.2.3