lib/vestal_versions.rb in laserlemon-vestal_versions-0.4.1 vs lib/vestal_versions.rb in laserlemon-vestal_versions-0.4.2

- old
+ new

@@ -3,99 +3,110 @@ module LaserLemon module VestalVersions def self.included(base) base.extend ClassMethods end - + module ClassMethods def versioned has_many :versions, :as => :versioned, :order => 'versions.number ASC', :dependent => :destroy do def at(value) case value - when Version: value - when Numeric: find_by_number(value.floor) - when Symbol: respond_to?(value) ? send(value) : nil - when Date, Time: last(:conditions => ['versions.created_at <= ?', value.to_time.in_time_zone]) + when Version: value + when Numeric: find_by_number(value.floor) + when Symbol: respond_to?(value) ? send(value) : nil + when Date, Time: last(:conditions => ['versions.created_at <= ?', value.to_time]) end end - + def between(from_value, to_value) from, to = number_at(from_value), number_at(to_value) return [] if from.nil? || to.nil? || (from == to) all( :conditions => {:number => Range.new(*[from, to].sort)}, :order => "versions.number #{(from > to) ? 'DESC' : 'ASC'}" ) end - + private - - def number_at(value) - case value - when Version: value.number - when Numeric: value.floor - when Symbol, Date, Time: at(value).try(:number) + + def number_at(value) + case value + when Version: value.number + when Numeric: value.floor + when Symbol, Date, Time: at(value).try(:number) + end end - end end - + after_save :create_version, :if => :needs_version? - + include InstanceMethods end end - + module InstanceMethods private - - def needs_version? - !changed.empty? - end - - def create_version - if versions.empty? - versions.create(:changes => attributes, :number => 1) - else - @version = nil - versions.create(:changes => changes, :number => (version.to_i + 1)) + + def needs_version? + !changed.empty? end - - @version = nil - end - + + def reset_version(new_version = nil) + @version = new_version + end + + def create_version + if versions.empty? + versions.create(:changes => attributes, :number => 1) + else + reset_version + versions.create(:changes => changes, :number => (version.to_i + 1)) + end + + reset_version + end + public - - def version - @version ||= versions.maximum(:number) - end - - def revert_to(value) - chain = versions.between(version, value) - return version unless chain.size > 1 - - new_version, backward = chain.last.number, (chain.first > chain.last) - backward ? chain.pop : chain.shift - - chain.each do |version| - version.changes.except('updated_at', 'updated_on').each do |attribute, change| - write_attribute(attribute, backward ? change.first : change.last) + + def version + @version ||= versions.maximum(:number) + end + + def revert_to(value) + chain = versions.between(version, value) + return version unless chain.size > 1 + + new_version = chain.last.number + backward = chain.first > chain.last + backward ? chain.pop : chain.shift + + timestamps = %w(created_at created_on updated_at updated_on) + + chain.each do |version| + version.changes.except(*timestamps).each do |attribute, change| + new_value = backward ? change.first : change.last + write_attribute(attribute, new_value) + end end + + reset_version(new_version) end - - @version = new_version - end - - def revert_to!(value) - revert_to(value) && save - end - - def last_changes - versions.at(version).changes - end - - def last_changed - last_changes.keys - end + + def revert_to!(value) + revert_to(value) + reset_version if saved = save + saved + end + + def last_changes + return {} if version == 1 + versions.at(version).changes + end + + def last_changed + last_changes.keys + end end end end ActiveRecord::Base.send(:include, LaserLemon::VestalVersions)