DestroyedAt
Looking for help?
If it is a bug please open an issue on GitHub.
Installation
Add the destroyed_at
gem to your Gemfile
gem 'destroyed_at'
You can either mixin the modules on a case-by-case basis:
class User < ActiveRecord::Base
include DestroyedAt
end
or make the changes globally:
class ActiveRecord::Base
include DestroyedAt
end
Please note you will need to make a migration
Each model's table that is expected to have this behavior must have
a destroyed_at
column of type DateTime
.
It is recommended that you add an index on the model's destroyed_at
column,
so that your database does not have to do a table scan for every query.
Only Postgres' query indexes will be of any benefit:
CREATE INDEX ON users WHERE destroyed_at IS NULL;
CREATE INDEX ON users WHERE destroyed_at IS NOT NULL;
Usage
Allows you to "destroy" an object without deleting the record or associated records.
Destroying
Overides #destroy
to set #destroyed_at
to the current time on an object. The
default scope of the class is then set to return objects that have not
been destroyed (i.e., have nil
for their destroyed_at value).
#destroyed?
will be true
when your model is destroyed; it will be
false
when your model has been restored.
class User < ActiveRecord::Base
include DestroyedAt
end
user = User.create
user.destroy
# => true
user.destroyed_at
# => <DateTime>
Warning: Dependent relations with destroy
Be careful when destroying models that have dependent: :destroy
. This will delete, not destroy, the associated model if
said model does not include DestroyedAt
.
Restoring
When you'd like to "restore" a record, call the #restore
method on
the instance. This will set its #destroyed_at
value to nil
, thereby
including it in the default scope of the class again.
To include this functionality on has_many through
relationships,
be sure to include DestroyedAt
on the through model, as well as the
parent model.
class User < ActiveRecord::Base
include DestroyedAt
end
user = User.create
user.destroy
user.restore
# => true
user.destroyed_at
# => nil
Destroyed Scope
When you include the DestroyedAt
module, it sets a default scope of
where(destroyed_at: nil)
. It also defines a scope called .destroyed
which removes the default scope and finds the records of a relation
where.not(destroyed_at: nil)
. This is different than calling unscoped
on the class/relation. Where unscoped will remove all scoping from a
relation, .destroyed
only removes the default scope generated by the
DestroyedAt
module, making it safe to call on relations.
Callbacks
before_restore
, after_restore
and around_restore
callbacks are added to your
model. They work similarly to the before_destroy
, after_destroy
and around_restore
callbacks.
class User < ActiveRecord::Base
before_restore :before_restore_action
after_restore :after_restore_action
around_restore :around_restore_action
private
def before_restore_action
...
end
def after_restore_action
...
end
def around_restore_action
# before around
yield # restoring...
# after around
end
Validations
If you are using the uniqueness
validator you will need to run it as:
validates :email, uniqueness: { conditions: -> { where(destroyed_at: nil) } }
Rails will by default not include default_scopes when querying for uniqueness. Rather than monkey patching the validator we believe this is the best solution.
Authors
We are very thankful for the many contributors
Versioning
This gem follows Semantic Versioning
Want to help?
Please do! We are always looking to improve this gem. Please see our Contribution Guidelines on how to properly submit issues and pull requests.
Legal
DockYard Inc. ยฉ 2014