12/08/2018, 13:41

Soft Delete with Paranoia

What does "Soft Delete" mean? Soft deleting an item from a database means that the row or entity is marked as deleted but not physically removed from the database. Instead it is hidden from normal users of the system but may be accessible by database or system administrators. Soft Delete ...

091814_1453_mds201220141.png

What does "Soft Delete" mean?

Soft deleting an item from a database means that the row or entity is marked as deleted but not physically removed from the database. Instead it is hidden from normal users of the system but may be accessible by database or system administrators.

Soft Delete in Ruby on Rails

In Ruby on Rails, there are many gems for Soft Delete. Today, I will introduce of of the most popular one is called Paranoia.

When your app is using Paranoia, calling destroy on an ActiveRecord object doesn't actually destroy the database record, but just hides it. Paranoia does this by setting a deleted_at field to the current time when you destroy a record, and hides it by scoping all queries on your model to only include records which do not have a deleted_at field.

Installation

`gem "paranoia", "~> 2.0"`

then: bundle install

Usage

Add deleted_at field to your model migrate file.

    class CreateArticles < ActiveRecord::Migration
      def change
        create_table :articles do |t|
          t.text :title
          t.text :content
          t.datetime :deleted_at, index: true
          t.timestamps null: false
        end
      end
    end

In your model:

    class Article < ActiveRecord::Base
      acts_as_paranoid

      # ...
    end

Now you can start your soft delete:

    Article.first.destroy

This will not delete first article from your database, but change deleted_at from nil to current timestamp.

That's it! Look, it is simple and strong. But how if you really want to hard destroy first artcle from your database?

    Article.first.really_destroy!

Now first article is forever gone.

If you want to use a column other than deleted_at, you can pass it as an option:

    class Article < ActiveRecord::Base
        acts_as_paranoid column: :destroyed_at
        #...
    end

Finding records

    Article.all

This will find only the article that is not deleted. If you want to find all records (both delete and not delete)

     Article.with_deleted

If you want to find only the deleted records:

    Article.only_deleted

If you want to check if a record is soft-deleted:

    Article.first.paranoia_destroyed?
    #or
    Article.first.deleted?

Restoring deleted record

For instance, you want to restore the first record:

    Article.first.restore
    #or
    Article.restore 1

If you want to restore a many records at once:

    Article.restore([id1, id2, ..., idN])

If you want to restore first record and their dependently destroyed associated records:

    Article.restore(1, recursive: true)
    # or
    Article.first.restore recursive: true

Callbacks

Paranoia provides several callbacks. Below are some callbacks of Paranoia:

    class Article < ActiveRecord::Base
      after_destroy      :method1
      after_restore      :method2
      after_real_destroy :method3
      #...
    end

You can use these events just like regular Rails callbacks with before, after.

It is too simple, but useful. Hope that this article is useful for all Rails developers. For more details, find the references below:

Paranoia Gem: https://github.com/rubysherpas/paranoia

Go Rails: https://gorails.com/episodes/soft-delete-with-paranoia

How To Configure Ruby on Rails With Paranoia Gem: https://www.netguru.co/tips/how-to-configure-ruby-on-rails-with-paranoia-gem

0