lib/versioned.rb in mrkurt-versioned-0.1.0 vs lib/versioned.rb in mrkurt-versioned-0.1.1

- old
+ new

@@ -1,16 +1,68 @@ require 'version' module Versioned + class StaleDocumentError < MongoMapper::MongoMapperError; end def self.included(base) base.extend ClassMethods base.class_eval do versioned end end + module LockingInstanceMethods + private + #new? isn't working + def is_new_document? + (read_attribute(self.version_lock_key).blank? && changes[self.version_lock_key.to_s].blank?) || + (changes[self.version_lock_key.to_s] && changes[self.version_lock_key.to_s].first.blank?) + end + def prep_lock_version + old = read_attribute(self.version_lock_key) + if !is_new_document? || old.blank? + v = (Time.now.to_f * 1000).ceil.to_s + write_attribute self.version_lock_key, v + end + + old + end + + def save_to_collection(options = {}) + current_version = prep_lock_version + if is_new_document? + collection.insert(to_mongo, :safe => true) + else + selector = { :_id => read_attribute(:_id), self.version_lock_key => current_version } + #can't upsert, safe must be true for this to work + result = collection.update(selector, to_mongo, :upsert => false, :safe => true) + + if result.is_a?(Array) && result[0][0]['updatedExisting'] == false + write_attribute self.version_lock_key, current_version + raise StaleDocumentError.new + elsif !result.is_a?(Array) + #wtf? + write_attribute self.version_lock_key, current_version + raise "Unexpected result from mongo" + end + + selector[:_id] + end + end + end module ClassMethods + def locking!(options = {}) + include(LockingInstanceMethods) + class_inheritable_accessor :version_lock_key + self.version_lock_key = options[:key] || :lock_version + key self.version_lock_key, Integer + + if self.respond_to?(:version_use_key) + self.version_use_key = self.version_lock_key + (self.version_except_columns ||= []) << self.version_lock_key.to_s #don't version the lock key + end + end + def versioned(options = {}) class_inheritable_accessor :version_only_columns self.version_only_columns = Array(options[:only]).map(&:to_s).uniq if options[:only] class_inheritable_accessor :version_except_columns self.version_except_columns = Array(options[:except]).map(&:to_s).uniq if options[:except] @@ -57,10 +109,11 @@ after_update :create_version, :if => :needs_version? include InstanceMethods alias_method_chain :reload, :versions end + end module InstanceMethods private def versioned_columns @@ -135,11 +188,11 @@ changes end end def revert - revert_to self.version -1 + revert_to self.versions.at(self.version).previous end def retrieve_version n versions.find_by_number(n).changes.each do |n,v| self.send("#{n.to_sym}=",v.first) @@ -163,10 +216,10 @@ reset_version if saved = save saved end def latest_changes - return {} if version.nil? || version == 1 + return {} if version.nil? versions.at(version).changes end end end