# encoding: utf-8 module MongoidExt #:nodoc: # Include this module to get soft deletion of root level documents. # This will add a deleted_at field to the +Document+, managed automatically. # Potentially incompatible with unique indices. (if collisions with deleted items) # # To use: # # class Person # include Mongoid::Document # include MongoidExt::Paranoia # end module Paranoia extend ActiveSupport::Concern included do end # Delete the paranoid +Document+ from the database completely. This will # run the destroy callbacks. # # Example: # # <tt>document.destroy!</tt> def destroy! run_callbacks(:destroy) { delete! } end # Delete the paranoid +Document+ from the database completely. # # Example: # # <tt>document.delete!</tt> def delete! Mongoid::Persistence::Remove.new(self).persist end # Delete the +Document+, will set the deleted_at timestamp and not actually # delete it. # # Example: # # <tt>document.remove</tt> # # Returns: # # true def remove(options = {}) self.class.paranoia_klass.create(:document => self.raw_attributes) super end alias :delete :remove module ClassMethods #:nodoc: # Find deleted documents # # Examples: # # <tt>Person.deleted</tt> # all deleted employees # <tt>Company.first.employees.deleted</tt> # works with a join # <tt>Person.deleted.find("4c188dea7b17235a2a000001").first</tt> # <tt>Person.deleted.compact!(1.week.ago)</tt> def deleted self.paranoia_klass end def paranoia_klass parent_klass = self @paranoia_klass ||= Class.new do include Mongoid::Document include Mongoid::Timestamps cattr_accessor :parent_class self.parent_class = parent_klass self.collection_name = "#{self.parent_class.collection_name}.trash" field :document, :type => Hash before_validation :set_id, :on => :create def restore self.class.parent_class.create(self.document) end def self.compact!(date = 1.month.ago) self.delete_all(:created_at.lte => date) end private def set_id self["_id"] = self.document["_id"] end end end end end end