module SoftDelete::SoftDeletable

TODO: wrap in a transaction

Public Class Methods

dependent(behavior = :ignore) click to toggle source

descibes how soft delete should handle dependencies ignore ignore dependencies and do nothing. this is the default behavior default fire off the same action that is described by ar dsl soft_delete if dsl is :destroy, then override with a soft_delete

# File lib/soft_delete/soft_deletable.rb, line 31
def self.dependent(behavior = :ignore)
  raise ArgumentError unless %i[ignore default soft_delete].include? behavior

  @@soft_delete_dependency_behavior = behavior
  self
end
not_scoped() click to toggle source
# File lib/soft_delete/soft_deletable.rb, line 18
def self.not_scoped
  @@include_default_scope = false

  self
end

Public Instance Methods

soft_delete(validate: true) click to toggle source
# File lib/soft_delete/soft_deletable.rb, line 38
def soft_delete(validate: true)
  soft_delete!(validate: validate)
rescue ActiveRecord::RecordInvalid
  false
end
soft_delete!(validate: true) click to toggle source
# File lib/soft_delete/soft_deletable.rb, line 44
def soft_delete!(validate: true)
  ActiveRecord::Base.transaction do
    handle_soft_delete_dependency_behavior
    run_callbacks(:destroy) do
      self.deleted_at = Time.now
      save!(validate: validate)
    end
  end
end

Private Instance Methods

handle_normal_dependencies() click to toggle source
# File lib/soft_delete/soft_deletable.rb, line 67
def handle_normal_dependencies
  soft_delete_dependent_associations.each(&:handle_dependency)
end
handle_overridden_soft_delete_dependencies() click to toggle source
# File lib/soft_delete/soft_deletable.rb, line 71
def handle_overridden_soft_delete_dependencies
  soft_delete_dependent_associations.each do |assn|
    next unless assn.options[:dependent] == :destroy

    # TODO: pass in validate
    assn.load_target.each(&:soft_delete!)

    # see:
    # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/collection_association.rb#L174
    assn.reset
    assn.loaded!
  end
  handle_normal_dependencies
end
handle_soft_delete_dependency_behavior() click to toggle source
# File lib/soft_delete/soft_deletable.rb, line 56
def handle_soft_delete_dependency_behavior
  return unless @@soft_delete_dependency_behavior.present?

  case @@soft_delete_dependency_behavior
  when :soft_delete
    handle_overridden_soft_delete_dependencies
  when :default
    handle_normal_dependencies
  end
end
soft_delete_dependent_associations() click to toggle source
# File lib/soft_delete/soft_deletable.rb, line 86
def soft_delete_dependent_associations
  @soft_delete_dependent_associations ||=
    _reflections.select { |_k, v| v.options[:dependent].present? }.map { |_k, v| association(v.name) }
end