Skip to content
This repository


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Rails 3 compatible soft destroy implementation

branch: master

Fetching latest commit…


Cannot retrieve the latest commit at this time

Octocat-spinner-32 lib
Octocat-spinner-32 spec
Octocat-spinner-32 test
Octocat-spinner-32 .gitignore
Octocat-spinner-32 Gemfile
Octocat-spinner-32 MIT-LICENSE
Octocat-spinner-32 README.textile
Octocat-spinner-32 Rakefile
Octocat-spinner-32 VERSION
Octocat-spinner-32 init.rb
Octocat-spinner-32 install.rb
Octocat-spinner-32 soft_destroyable.gemspec
Octocat-spinner-32 uninstall.rb


Allows one to annotate an ActiveRecord module as being soft_destroyable.

Why another soft_destroy implementation?

This gem was inspired by acts_as_paranoid and
rails3_acts_as_paranoid, both of which are great gems.
I found that rails3_acts_as_paranoid did not handle associations the way I wanted (at least at the time I wrote this),
so I wrote this implementation instead.


This changes the behavior of the destroy method to become a soft-destroy, which
will set the deleted_at attribute to, and the deleted attribute to true
It exposes the revive method to reverse the effects of destroy (for :dependent => :destroy associations only).
It also exposes the destroy! method which can be used to really destroy an object and it’s associations.

revive will not revive child associations which have been destroyed by actions other a destroy of the parent.
This requires the column attribute revive_with_parent.

Standard ActiveRecord destroy callbacks are not called, however you can override before_soft_destroy, after_soft_destroy,
and before_destroy! on your soft_destroyable models.

Standard ActiveRecord dependent options :destroy, :restrict, :nullify, :delete_all, and :delete are supported and will
behave as expected. revive will not undo the effects of nullify, delete_all, and delete.
restrict is effected by the deleted? state. In other words, deleted child models will not raise a restriction when
destroying the parent.

The delete operation is not modified by this module.

The operations: destroy, destroy!, and revive are automatically delegated to the dependent association records.
in a single transaction.

Scopes are provided for deleted and not_deleted. The standard all scope is not polluted, so will still
return all records, deleted or not.

Author: Michael Kintzer


  • Migrate your model to add deleted and deleted_at attributes. There are helpers provided for this:

  create_table :mytable do |t|

  change_table :mytable do |t|

  • Annotate your model to be soft_destroyable

  class Parent
    has_many :children, :dependent => :restrict
    has_many :animals, :dependent => :nullify

  • That’s it!


  • make sure you have rails and sqlite gems installed.
  • rake test

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don’t break it in a
    future version unintentionally.
  • Commit, do not mess with rakefile, version, or history.
    (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request


h3. Copyright

Copyright © 2010-11 Michael Kintzer, released under the MIT license

Something went wrong with that request. Please try again.