Created
September 27, 2012 10:08
-
-
Save stan/3793263 to your computer and use it in GitHub Desktop.
Revisions
-
s12chung created this gist
Sep 26, 2011 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,86 @@ module Mongoid module Undo extend ActiveSupport::Concern included do include Mongoid::Document field :version, type: Integer, default: 0 before_save :prepare_versioning after_save :create_version before_destroy :version_destroy end def versions; ::Version.where(obj_id: id) end def versions_gt(version = self.version); versions.where(:version.gt => version) end def version_at(version = self.version); versions.where(version: version).first end def current_version; version_at end def previous_version; version_at version - 1 end def versioned?; version > 0 end def has?(ver) ver.obj_id == id && ver.obj_class == self.class.to_s end def matches?(ver) has?(ver) && ver.obj_attributes == attributes && ver.version == version end def undo!; rollback_to!(version - 1) end def rollback_to!(version) unless persisted?; return false end if version == 0 versions.destroy without_versioning :destroy attributes else ver = version_at(version) unless ver; return false end ver.rollback_to(self) end end def without_versioning(method = nil) @without_versioning = true method ? method.to_proc.call(self) : yield ensure @without_versioning = false end private def match_persisted? current_version && attributes == current_version.obj_attributes end def prepare_versioning if !@without_versioning if version == 0 && persisted? self.version += 1 old_self = self.class.find(id) old_self.version += 1 old_self.send(:create_version) end if !match_persisted?; self.version += 1 end end end def create_version(destroy = false) if !@without_versioning && (destroy || !match_persisted?) ver = ::Version.new(obj_id: id, obj_class: self.class.to_s, version: version) unless destroy; ver.attributes = ver.attributes.merge({:obj_attributes => attributes}) end ver.save! end end def version_destroy if !@without_versioning self.version += 1 without_versioning(:save) create_version(true) end end end end This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,48 @@ module Mongoid::Undo module Version extend ActiveSupport::Concern included do include Mongoid::Document include Mongoid::Timestamps::Created field :obj_id field :obj_class field :obj_attributes, type: Hash field :version, type: Integer validates_presence_of(fields.keys - ['_id', '_type', 'created_at', 'obj_attributes']) end def obj; obj_class.constantize.find(obj_id) end def created?; version == 1 end def deleted?; !obj_attributes end def modified?; !(created? || deleted?) end def latest?(obj = nil) unless obj; obj = self.obj end obj.nil? || version == obj.version end def rollback_to(obj = nil) if !deleted? if obj.nil? || obj.id != obj_id; obj = self.obj end if obj.nil?; obj = obj_class.constantize.new end obj.versions_gt(version).each {|ver| ver.destroy } rollback(obj) else false end end private def rollback(obj = nil) old_attributes = obj.attributes obj.attributes = obj_attributes obj.without_versioning :save old_attributes end end end