instance method
restore_transaction_record_state
Ruby on Rails edge
Since v3.0.20 Private — implementation detail, not part of the public APISignature
restore_transaction_record_state(force_restore_state = false)
Restore the new record state and id of a record that was previously saved by a call to save_record_state.
Parameters
-
force_restore_stateopt = false
Source
# File activerecord/lib/active_record/transactions.rb, line 493
def restore_transaction_record_state(force_restore_state = false)
if restore_state = @_start_transaction_state
if force_restore_state || restore_state[:level] <= 1
@new_record = restore_state[:new_record]
@previously_new_record = restore_state[:previously_new_record]
@destroyed = restore_state[:destroyed]
locking_column = self.class.locking_column if self.class.locking_enabled?
@attributes = restore_state[:attributes].map do |attr|
if attr.name == locking_column
# The locking column is bumped by `_update_row` itself, not the caller, and
# `_update_row` writes the new value into the same `@attributes` object that
# the snapshot is holding a reference to (because the snapshot wraps the
# `AttributeSet` rather than deep-duping it). After a successful save,
# `forget_attribute_assignments` reassigns `@attributes`, so subsequent
# operations see a clean attribute, but the snapshot retains the dirty one.
# Forcibly rebuild the locking column attribute from its (still-correct)
# original value so the next save uses the pristine value in the WHERE
# clause and doesn't raise `StaleObjectError` after a rollback.
next attr.with_value_from_database(attr.original_value)
end
value = @attributes.fetch_value(attr.name)
attr = attr.with_value_from_user(value) if attr.value != value
attr
end
@mutations_from_database = nil
@mutations_before_last_save = nil
columns = self.class.primary_key_definition.columns
restored_id = Array(restore_state[:id])
if columns.map { |col| @attributes.fetch_value(col) } != restored_id
columns.zip(restored_id).each do |col, val|
@attributes.write_from_user(col, val)
end
end
freeze if restore_state[:frozen?]
elsif self.class.locking_enabled?
# Nested savepoint rollback. The full restore above only runs at the
# outermost level, but the same `_update_row` mutation that bumps the
# in-memory locking column happens for saves performed inside the
# savepoint too. Leaving the bumped value in memory after the
# savepoint reverts those rows raises `StaleObjectError` on the next
# save in the surrounding transaction. Reset just the locking column
# so subsequent saves can match the row that the savepoint restored.
locking_column = self.class.locking_column
attr = restore_state[:attributes][locking_column]
if attr
@attributes.write_from_database(locking_column, attr.original_value)
end
end
end
end
Defined in activerecord/lib/active_record/transactions.rb line 493
· View on GitHub
· Improve this page
· Find usages on GitHub
Defined in ActiveRecord::Transactions