aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2018-03-04 01:56:49 +0900
committerRyuta Kamizono <kamipo@gmail.com>2018-03-05 09:52:58 +0900
commit37984353f272efb12cb1d008cb231a1f1e56524a (patch)
treed6dd4d4910f1867befdce0eb6c87353c2b0977c6 /activerecord
parent4331478996d6086bb089c1e33956a1c0fa9000b1 (diff)
downloadrails-37984353f272efb12cb1d008cb231a1f1e56524a.tar.gz
rails-37984353f272efb12cb1d008cb231a1f1e56524a.tar.bz2
rails-37984353f272efb12cb1d008cb231a1f1e56524a.zip
Prefer `_update_record` than `update_all` for updating a record
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb7
-rw-r--r--activerecord/lib/active_record/persistence.rb56
2 files changed, 35 insertions, 28 deletions
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index cae7a66fcc..c2f740a1e0 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -91,13 +91,10 @@ module ActiveRecord
attribute_names.push(lock_col)
- relation = self.class.unscoped
-
- affected_rows = relation.where(
+ affected_rows = self.class._update_record(
+ attributes_with_values_for_update(attribute_names),
self.class.primary_key => id_in_database,
lock_col => previous_lock_value
- ).update_all(
- attributes_with_values_for_update(attribute_names)
)
unless affected_rows == 1
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 28308da96d..610f11b66c 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -187,10 +187,11 @@ module ActiveRecord
connection.insert(im, "#{self} Create", primary_key || false, primary_key_value)
end
- def _update_record(values, id) # :nodoc:
- bind = predicate_builder.build_bind_attribute(primary_key, id)
+ def _update_record(values, constraints) # :nodoc:
+ constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
+
um = arel_table.where(
- arel_attribute(primary_key).eq(bind)
+ constraints.reduce(&:and)
).compile_update(_substitute_values(values), primary_key)
connection.update(um, "#{self} Update")
@@ -463,13 +464,16 @@ module ActiveRecord
verify_readonly_attribute(key.to_s)
end
- updated_count = _relation_for_itself.update_all(attributes)
+ affected_rows = self.class._update_record(
+ attributes,
+ self.class.primary_key => id_in_database
+ )
attributes.each do |k, v|
write_attribute_without_type_cast(k, v)
end
- updated_count == 1
+ affected_rows == 1
end
# Initializes +attribute+ to zero if +nil+ and adds the value passed as +by+ (default is 1).
@@ -643,34 +647,37 @@ module ActiveRecord
end
time ||= current_time_from_proper_timezone
- attributes = timestamp_attributes_for_update_in_model
- attributes.concat(names)
-
- unless attributes.empty?
- changes = {}
+ attribute_names = timestamp_attributes_for_update_in_model
+ attribute_names.concat(names)
- attributes.each do |column|
- column = column.to_s
- changes[column] = write_attribute(column, time)
+ unless attribute_names.empty?
+ attribute_names.each do |attr_name|
+ write_attribute(attr_name, time)
end
- scope = _relation_for_itself
+ constraints = { self.class.primary_key => id_in_database }
if locking_enabled?
locking_column = self.class.locking_column
- scope = scope.where(locking_column => read_attribute_before_type_cast(locking_column))
- changes[locking_column] = increment_lock
+ constraints[locking_column] = read_attribute_before_type_cast(locking_column)
+ attribute_names << locking_column
+ increment_lock
end
- clear_attribute_changes(changes.keys)
- result = scope.update_all(changes) == 1
+ clear_attribute_changes(attribute_names)
+
+ affected_rows = self.class._update_record(
+ attributes_with_values_for_update(attribute_names),
+ constraints
+ )
+
+ result = affected_rows == 1
if !result && locking_enabled?
raise ActiveRecord::StaleObjectError.new(self, "touch")
end
@_trigger_update_callback = result
- result
else
true
end
@@ -707,16 +714,19 @@ module ActiveRecord
attribute_names &= self.class.column_names
attributes_values = attributes_with_values_for_update(attribute_names)
if attributes_values.empty?
- rows_affected = 0
+ affected_rows = 0
@_trigger_update_callback = true
else
- rows_affected = self.class._update_record(attributes_values, id_in_database)
- @_trigger_update_callback = rows_affected > 0
+ affected_rows = self.class._update_record(
+ attributes_values,
+ self.class.primary_key => id_in_database
+ )
+ @_trigger_update_callback = affected_rows == 1
end
yield(self) if block_given?
- rows_affected
+ affected_rows
end
# Creates a record with values matching those of the instance attributes