From 5b61168aafb28b9d4dcbe7651d6a5a63cdb68b32 Mon Sep 17 00:00:00 2001
From: Emilio Tagua <miloops@gmail.com>
Date: Thu, 30 Apr 2009 13:21:13 -0300
Subject: Added arel_attributes_values methods, refactored locking and
 AR#update to use this method

---
 activerecord/lib/active_record/base.rb             | 32 ++++++++++++++++------
 .../lib/active_record/locking/optimistic.rb        |  9 +-----
 2 files changed, 24 insertions(+), 17 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 8882a00dd5..5807d62f2a 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1077,7 +1077,7 @@ module ActiveRecord #:nodoc:
 
        # Returns an array of all the attributes that have been specified as readonly.
        def readonly_attributes
-         read_inheritable_attribute(:attr_readonly)
+         read_inheritable_attribute(:attr_readonly) || []
        end
 
       # If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object,
@@ -2946,14 +2946,9 @@ module ActiveRecord #:nodoc:
       # Updates the associated record with values matching those of the instance attributes.
       # Returns the number of affected rows.
       def update(attribute_names = @attributes.keys)
-        quoted_attributes = attributes_with_quotes(false, false, attribute_names)
-        return 0 if quoted_attributes.empty?
-        connection.update(
-          "UPDATE #{self.class.quoted_table_name} " +
-          "SET #{quoted_comma_pair_list(connection, quoted_attributes)} " +
-          "WHERE #{connection.quote_column_name(self.class.primary_key)} = #{quote_value(id)}",
-          "#{self.class.name} Update"
-        )
+        attributes_with_values = arel_attributes_values(false, false, attribute_names)
+        return 0 if attributes_with_values.empty?
+        table.where(table[self.class.primary_key].eq(id)).update(attributes_with_values)
       end
 
       # Creates a record with values matching those of the instance attributes
@@ -3063,6 +3058,25 @@ module ActiveRecord #:nodoc:
         include_readonly_attributes ? quoted : remove_readonly_attributes(quoted)
       end
 
+      def table
+        @arel_table ||= Arel(self.class.table_name)
+      end
+
+      def arel_attributes_values(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
+        attrs = {}
+        connection = self.class.connection
+        attribute_names.each do |name|
+          if (column = column_for_attribute(name)) && (include_primary_key || !column.primary)
+            value = read_attribute(name)
+
+            if include_readonly_attributes || (!include_readonly_attributes && !self.class.readonly_attributes.include?(name))
+              attrs[table[name]] = value
+            end
+          end
+        end
+        attrs
+      end
+
       # Quote strings appropriately for SQL statements.
       def quote_value(value, column = nil)
         self.class.connection.quote(value, column)
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 1251e9f013..bb28444b07 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -89,18 +89,11 @@ module ActiveRecord
           attribute_names.uniq!
 
           begin
-            table = Arel(self.class.table_name)
-
-            attributes = {}
-            attributes_with_quotes(false, false, attribute_names).map { |k,v|
-              attributes.merge!(table[k] => v)
-            }
-
             affected_rows = table.where(
               table[self.class.primary_key].eq(quoted_id).and(
                 table[self.class.locking_column].eq(quote_value(previous_value))
               )
-            ).update(attributes)
+            ).update(arel_attributes_values(false, false, attribute_names))
 
 
             unless affected_rows == 1
-- 
cgit v1.2.3