module ActsAsParanoid::Core

Public Class Methods

included(base) click to toggle source
# File lib/acts_as_paranoid/core.rb, line 5
def self.included(base)
  base.extend ClassMethods
end

Public Instance Methods

delete() click to toggle source

Straight from ActiveRecord 5.1!

# File lib/acts_as_paranoid/core.rb, line 142
def delete
  self.class.delete(id) if persisted?
  stale_paranoid_value
  freeze
end
deleted?() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 227
def deleted?
  return true if @destroyed

  if self.class.string_type_with_deleted_value?
    paranoid_value == paranoid_configuration[:deleted_value]
  elsif self.class.boolean_type_not_nullable?
    paranoid_value == true
  else
    !paranoid_value.nil?
  end
end
Also aliased as: destroyed?
deleted_fully?() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 241
def deleted_fully?
  @destroyed
end
Also aliased as: destroyed_fully?
destroy() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 173
def destroy
  if !deleted?
    with_transaction_returning_status do
      run_callbacks :destroy do
        if persisted?
          # Handle composite keys, otherwise we would just use
          # `self.class.primary_key.to_sym => self.id`.
          self.class
            .delete_all([Array(self.class.primary_key), Array(id)].transpose.to_h)
          decrement_counters_on_associations
        end

        @_trigger_destroy_callback = true

        stale_paranoid_value
        self
      end
    end
  elsif paranoid_configuration[:double_tap_destroys_fully]
    destroy_fully!
  end
end
destroy!() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 167
def destroy!
  destroy || raise(
    ActiveRecord::RecordNotDestroyed.new("Failed to destroy the record", self)
  )
end
destroy_fully!() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 148
def destroy_fully!
  with_transaction_returning_status do
    run_callbacks :destroy do
      destroy_dependent_associations!

      if persisted?
        # Handle composite keys, otherwise we would just use
        # `self.class.primary_key.to_sym => self.id`.
        self.class
          .delete_all!([Array(self.class.primary_key), Array(id)].transpose.to_h)
        decrement_counters_on_associations
      end

      @destroyed = true
      freeze
    end
  end
end
destroyed?()
Alias for: deleted?
destroyed_fully?()
Alias for: deleted_fully?
paranoid_value() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 137
def paranoid_value
  send(self.class.paranoid_column)
end
persisted?() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 133
def persisted?
  !(new_record? || @destroyed)
end
recover(options = {}) click to toggle source
# File lib/acts_as_paranoid/core.rb, line 196
def recover(options = {})
  return if !deleted?

  options = {
    recursive: self.class.paranoid_configuration[:recover_dependent_associations],
    recovery_window: self.class.paranoid_configuration[:dependent_recovery_window],
    raise_error: false
  }.merge(options)

  self.class.transaction do
    run_callbacks :recover do
      increment_counters_on_associations
      deleted_value = paranoid_value
      self.paranoid_value = self.class.recovery_value
      result = if options[:raise_error]
                 save!
               else
                 save
               end
      recover_dependent_associations(deleted_value, options) if options[:recursive]
      result
    end
  end
end
recover!(options = {}) click to toggle source
# File lib/acts_as_paranoid/core.rb, line 221
def recover!(options = {})
  options[:raise_error] = true

  recover(options)
end

Private Instance Methods

decrement_counters_on_associations() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 324
def decrement_counters_on_associations
  update_counters_on_associations :decrement_counter
end
destroy_dependent_associations!() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 255
def destroy_dependent_associations!
  self.class.dependent_associations.each do |reflection|
    assoc = association(reflection.name)
    next unless (klass = assoc.klass).paranoid?

    klass
      .only_deleted.merge(get_association_scope(assoc))
      .each(&:destroy!)
  end
end
each_counter_cached_association_reflection() { |reflection| ... } click to toggle source
# File lib/acts_as_paranoid/core.rb, line 314
def each_counter_cached_association_reflection
  _reflections.each_value do |reflection|
    yield reflection if reflection.belongs_to? && reflection.counter_cache_column
  end
end
get_association_scope(dependent_association) click to toggle source
# File lib/acts_as_paranoid/core.rb, line 291
def get_association_scope(dependent_association)
  ActiveRecord::Associations::AssociationScope.scope(dependent_association)
end
increment_counters_on_associations() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 320
def increment_counters_on_associations
  update_counters_on_associations :increment_counter
end
paranoid_value=(value) click to toggle source
# File lib/acts_as_paranoid/core.rb, line 295
def paranoid_value=(value)
  write_attribute(self.class.paranoid_column, value)
end
recover_dependent_association(reflection, deleted_value, options) click to toggle source
# File lib/acts_as_paranoid/core.rb, line 266
def recover_dependent_association(reflection, deleted_value, options)
  assoc = association(reflection.name)
  return unless (klass = assoc.klass).paranoid?

  if reflection.belongs_to? && attributes[reflection.association_foreign_key].nil?
    return
  end

  scope = klass.only_deleted.merge(get_association_scope(assoc))

  # We can only recover by window if both parent and dependant have a
  # paranoid column type of :time.
  if self.class.paranoid_column_type == :time && klass.paranoid_column_type == :time
    scope = scope.deleted_inside_time_window(deleted_value, options[:recovery_window])
  end

  recovered = false
  scope.each do |object|
    object.recover(options)
    recovered = true
  end

  assoc.reload if recovered && reflection.has_one? && assoc.loaded?
end
recover_dependent_associations(deleted_value, options) click to toggle source
# File lib/acts_as_paranoid/core.rb, line 249
def recover_dependent_associations(deleted_value, options)
  self.class.dependent_associations.each do |reflection|
    recover_dependent_association(reflection, deleted_value, options)
  end
end
stale_paranoid_value() click to toggle source
# File lib/acts_as_paranoid/core.rb, line 328
def stale_paranoid_value
  self.paranoid_value = self.class.delete_now_value
  clear_attribute_changes([self.class.paranoid_column])
end
update_counters_on_associations(method_sym) click to toggle source
# File lib/acts_as_paranoid/core.rb, line 299
def update_counters_on_associations(method_sym)
  each_counter_cached_association_reflection do |assoc_reflection|
    reflection_options = assoc_reflection.options
    next unless reflection_options[:counter_cache]

    associated_object = send(assoc_reflection.name)
    next unless associated_object

    counter_cache_column = assoc_reflection.counter_cache_column
    associated_object.class.send(method_sym, counter_cache_column,
                                 associated_object.id)
    associated_object.touch if reflection_options[:touch]
  end
end