From ea45d56d3d23e703b2866524202649e333fd7408 Mon Sep 17 00:00:00 2001
From: Ryuta Kamizono <kamipo@gmail.com>
Date: Sun, 4 Mar 2018 00:39:53 +0900
Subject: Introduce `_delete_record` and use it for deleting a record

---
 .../lib/active_record/locking/optimistic.rb        | 22 +++++++++-------------
 activerecord/lib/active_record/persistence.rb      | 22 ++++++++++++++--------
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index c2f740a1e0..29735f5490 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -112,24 +112,20 @@ module ActiveRecord
         end
 
         def destroy_row
-          affected_rows = super
+          return super unless locking_enabled?
 
-          if locking_enabled? && affected_rows != 1
-            raise ActiveRecord::StaleObjectError.new(self, "destroy")
-          end
+          locking_column = self.class.locking_column
 
-          affected_rows
-        end
+          affected_rows = self.class._delete_record(
+            self.class.primary_key => id_in_database,
+            locking_column => read_attribute_before_type_cast(locking_column)
+          )
 
-        def relation_for_destroy
-          relation = super
-
-          if locking_enabled?
-            locking_column = self.class.locking_column
-            relation = relation.where(locking_column => read_attribute_before_type_cast(locking_column))
+          if affected_rows != 1
+            raise ActiveRecord::StaleObjectError.new(self, "destroy")
           end
 
-          relation
+          affected_rows
         end
 
         module ClassMethods
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 610f11b66c..7b0b7a18e3 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -197,6 +197,16 @@ module ActiveRecord
         connection.update(um, "#{self} Update")
       end
 
+      def _delete_record(constraints) # :nodoc:
+        constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
+
+        dm = Arel::DeleteManager.new
+        dm.from(arel_table)
+        dm.wheres = constraints
+
+        connection.delete(dm, "#{self} Destroy")
+      end
+
       private
         # Called by +instantiate+ to decide which class to use for a new
         # record instance.
@@ -311,7 +321,7 @@ module ActiveRecord
     # callbacks or any <tt>:dependent</tt> association
     # options, use <tt>#destroy</tt>.
     def delete
-      _relation_for_itself.delete_all if persisted?
+      _delete_row if persisted?
       @destroyed = true
       freeze
     end
@@ -690,15 +700,11 @@ module ActiveRecord
     end
 
     def destroy_row
-      relation_for_destroy.delete_all
-    end
-
-    def relation_for_destroy
-      _relation_for_itself
+      _delete_row
     end
 
-    def _relation_for_itself
-      self.class.unscoped.where(self.class.primary_key => id_in_database)
+    def _delete_row
+      self.class._delete_record(self.class.primary_key => id_in_database)
     end
 
     def create_or_update(*args, &block)
-- 
cgit v1.2.3