# DestroyedAt # [![Build Status](https://travis-ci.org/DockYard/ruby-destroyed_at.svg?branch=master)](http://travis-ci.org/dockyard/ruby-destroyed_at) [![Dependency Status](https://gemnasium.com/dockyard/ruby-destroyed_at.png?travis)](https://gemnasium.com/dockyard/ruby-destroyed_at) [![Code Climate](https://codeclimate.com/github/dockyard/ruby-destroyed_at/badges/gpa.svg)](https://codeclimate.com/github/dockyard/ruby-destroyed_at) ## Looking for help? ## If it is a bug [please open an issue on GitHub](https://github.com/dockyard/destroyed_at/issues). ## Installation ## Add the `destroyed_at` gem to your `Gemfile` ```ruby gem 'destroyed_at' ``` You can either mixin the modules on a case-by-case basis: ```ruby class User < ActiveRecord::Base include DestroyedAt end ``` or make the changes globally: ```ruby 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: ```db 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. ```ruby class User < ActiveRecord::Base include DestroyedAt end user = User.create user.destroy # => true user.destroyed_at # => ``` #### 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. ```ruby 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. ```ruby 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: ```ruby 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 ## * [Michael Dupuis](http://twitter.com/michaeldupuisjr) * [Brian Cardarella](http://twitter.com/bcardarella) [We are very thankful for the many contributors](https://github.com/dockyard/destroyed_at/graphs/contributors) ## Versioning ## This gem follows [Semantic Versioning](http://semver.org) ## Want to help? ## Please do! We are always looking to improve this gem. Please see our [Contribution Guidelines](https://github.com/dockyard/destroyed_at/blob/master/CONTRIBUTING.md) on how to properly submit issues and pull requests. ## Legal ## [DockYard](http://dockyard.com) Inc. © 2014 [@dockyard](http://twitter.com/dockyard) [Licensed under the MIT license](http://www.opensource.org/licenses/mit-license.php)