module ActiveRecord::Locking::Optimistic

def _clear_locking_column

def _clear_locking_column
  self[self.class.locking_column] = nil
  clear_attribute_change(self.class.locking_column)
end

def _create_record(attribute_names = self.attribute_names)

def _create_record(attribute_names = self.attribute_names)
  if locking_enabled?
    # We always want to persist the locking version, even if we don't detect
    # a change from the default, since the database might have no default
    attribute_names |= [self.class.locking_column]
  end
  super
end

def _lock_value_for_database(locking_column)

def _lock_value_for_database(locking_column)
  if will_save_change_to_attribute?(locking_column)
    @attributes[locking_column].value_for_database
  else
    @attributes[locking_column].original_value_for_database
  end
end

def _query_constraints_hash

def _query_constraints_hash
  return super unless locking_enabled?
  locking_column = self.class.locking_column
  super.merge(locking_column => _lock_value_for_database(locking_column))
end

def _touch_row(attribute_names, time)

def _touch_row(attribute_names, time)
  @_touch_attr_names << self.class.locking_column if locking_enabled?
  super
end

def _update_row(attribute_names, attempted_action = "update")

def _update_row(attribute_names, attempted_action = "update")
  return super unless locking_enabled?
  begin
    locking_column = self.class.locking_column
    lock_attribute_was = @attributes[locking_column]
    update_constraints = _query_constraints_hash
    attribute_names = attribute_names.dup if attribute_names.frozen?
    attribute_names << locking_column
    self[locking_column] += 1
    affected_rows = self.class._update_record(
      attributes_with_values(attribute_names),
      update_constraints
    )
    if affected_rows != 1
      raise ActiveRecord::StaleObjectError.new(self, attempted_action)
    end
    affected_rows
  # If something went wrong, revert the locking_column value.
  rescue Exception
    @attributes[locking_column] = lock_attribute_was
    raise
  end
end

def destroy_row

def destroy_row
  affected_rows = super
  if locking_enabled? && affected_rows != 1
    raise ActiveRecord::StaleObjectError.new(self, "destroy")
  end
  affected_rows
end

def increment!(*, **) # :nodoc:

:nodoc:
def increment!(*, **) # :nodoc:
  super.tap do
    if locking_enabled?
      self[self.class.locking_column] += 1
      clear_attribute_change(self.class.locking_column)
    end
  end
end

def initialize_dup(other) # :nodoc:

:nodoc:
def initialize_dup(other) # :nodoc:
  super
  _clear_locking_column if locking_enabled?
end

def locking_enabled? # :nodoc:

:nodoc:
def locking_enabled? # :nodoc:
  self.class.locking_enabled?
end