lib/vestal_versions/version.rb in vestal_versions-1.0.2 vs lib/vestal_versions/version.rb in vestal_versions-2.0.0

- old
+ new

@@ -1,19 +1,30 @@ +require 'active_record' +require 'active_support/configurable' + module VestalVersions # The ActiveRecord model representing versions. class Version < ActiveRecord::Base include Comparable + include ActiveSupport::Configurable # Associate polymorphically with the parent record. belongs_to :versioned, :polymorphic => true + if ActiveRecord::VERSION::MAJOR == 3 + attr_accessible :modifications, :number, :user, :tag, :reverted_from + end + # ActiveRecord::Base#changes is an existing method, so before serializing the +changes+ column, - # the existing +changes+ method is undefined. The overridden +changes+ method pertained to + # the existing +changes+ method is undefined. The overridden +changes+ method pertained to # dirty attributes, but will not affect the partial updates functionality as that's based on # an underlying +changed_attributes+ method, not +changes+ itself. undef_method :changes - serialize :changes, Hash + def changes + self[:modifications] + end + serialize :modifications, Hash # In conjunction with the included Comparable module, allows comparison of version records # based on their corresponding version numbers, creation timestamps and IDs. def <=>(other) [number, created_at, id].map(&:to_i) <=> [other.number, other.created_at, other.id].map(&:to_i) @@ -22,8 +33,52 @@ # Returns whether the version has a version number of 1. Useful when deciding whether to ignore # the version during reversion, as initial versions have no serialized changes attached. Helps # maintain backwards compatibility. def initial? number == 1 + end + + # Returns the original version number that this version was. + def original_number + if reverted_from.nil? + number + else + version = versioned.versions.at(reverted_from) + version.nil? ? 1 : version.original_number + end + end + + def restore! + model = restore + + if model + model.save! + destroy + end + + model + end + + def restore + if tag == 'deleted' + attrs = modifications + + class_name = attrs['type'].blank? ? versioned_type : attrs['type'] + klass = class_name.constantize + model = klass.new + + attrs.each do |k, v| + begin + model.send "#{k}=", v + rescue NoMethodError + logger.warn "Attribute #{k} does not exist on #{class_name} (Version id: #{id})." rescue nil + end + end + + model + else + latest_version = self.class.where(:versioned_id => versioned_id, :versioned_type => versioned_type, :tag => 'deleted').first + latest_version.nil? ? nil : latest_version.restore + end end end end