Hide your "deleted" data (unless specifically asked for) without resorting to default_scope
by leveraging in-line sub-selects. (See the Upgrading section)
- Ruby 2.3+
- ActiveRecord 4.1+
Add this line to your application's Gemfile:
gem 'deleted_at'
And then execute:
$ bundle
Or install it yourself as:
$ gem install deleted_at
Invoking with_deleted_at
sets the class up to use the deleted_at
functionality.
class User < ActiveRecord::Base
with_deleted_at
# the rest of your model code...
end
To work properly, the tables that back these models must have a deleted_at
timestamp column.
class AddDeletedAtColumnToUsers < ActiveRecord::Migration
def change
add_column :users, :deleted_at, 'timestamp with time zone'
end
end
If you're starting with a brand-new table, the existing timestamps
DSL has been extended to accept deleted_at: true
as an option, for convenience. Or you can do it seperately as shown above.
class CreatCommentsTable < ActiveRecord::Migration
def change
create_table :comments do |t|
# ...
# to the `timestamps` DSL
t.timestamps null: false, deleted_at: true
end
end
end
It's recommended (if your database engine supports it) to add partial indexes to the deleted_at
columns. Remember that indexes work best when they represent a minority of the rows. It's up to you to determine the best index for your table.
Example 1:
You have a thriving business and your customers love your product and rarely delete their account. You're likely to have way fewer rows WHERE deleted_at IS NOT NULL
.
class IndexDeletedAtColumns < ActiveRecord::Migration
def change
add_index :users, :deleted_at, where: "deleted_at IS NOT NULL"
end
end
Example 2:
You use expiring OAuth2 tokens as part of your application's authentication process. As time grows without bound rows WHERE deleted_at IS NULL
will pale in comparison.
class IndexDeletedAtColumns < ActiveRecord::Migration
def change
add_index :oauth_tokens, :deleted_at, where: "deleted_at IS NULL"
end
end
If you've used deleted_at
prior to v0.5.0, you'll need to migrate your schema. The new version of deleted_at
no longer uses views, instead constructing a subselect on the relations. This significantly reduces code polution and monkey patching, as well as reducing the runtime memory usage for rails. Your Database will look (and be) a lot cleaner with no deleted_at
views and your ERDs will be much cleaner as well.
Here is an example of a migration for upgrading
require 'deleted_at/legacy'
DeletedAt.disable
class UpgradeDeletedAt < ActiveRecord::Migration
def up
# hip hip hooray!
models.each do |model|
DeletedAt::Legacy.uninstall(model)
end
end
def down
# booo hiss
models.each do |model|
DeletedAt::Legacy.install(model)
end
end
private
def models
[
User,
Post
]
end
end
After checking out the repo, run bundle
to install dependencies. Then, run bundle exec rspec
to run the tests.
Bug reports and pull requests are welcome on GitHub at https://github.com/TwilightCoders/deleted_at. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.