Module: DataMapper::Has::Versions

Defined in:
lib/dm-has-versions/has/versions.rb

Defined Under Namespace

Modules: InstanceMethods Classes: RevertError

Instance Method Summary collapse

Instance Method Details

#has_versions(options = {}) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/dm-has-versions/has/versions.rb', line 6

def has_versions(options = {})
  ignores = [options[:ignore]].flatten.compact.map do |ignore|
    properties[ignore.to_s.intern]
  end

  class << self; self end.class_eval do
    define_method :const_missing do |name|
      storage_name = Extlib::Inflection.tableize(self.name + "Version")
      model = DataMapper::Model.new(storage_name)

      if name == :Version
        properties.each do |property|
          options = property.options
          model.property property.name, property.type, options
        end
        model.belongs_to self.storage_name.singular.intern

        self.const_set("Version", model)
      else
        super(name)
      end
    end
  end

  self.after_class_method :auto_migrate! do
    self::Version.auto_migrate!
  end

  self.after_class_method :auto_upgrade! do
    self::Version.auto_upgrade!
  end

  self.before :attribute_set do |property, value|
    pending_version_attributes[property] ||= self.attribute_get(property)
  end

  self.after :update do |result|
    if result && !dirty_attributes.except(*ignores).empty?
      break result if pending_version_attributes.empty?
      attributes = self.attributes.merge(pending_version_attributes)
      original_key = "#{self.class.storage_name.singular}_id"
      attributes[original_key.intern] = self.id
      version, latest = self.version, self.latest?
      transaction do
        self.revert_to!(version) unless latest
        self.class::Version.create(attributes.except(:id))
      end
      self.pending_version_attributes.clear
      @version = nil
    end

    result
  end

  self.after :destroy do |result|
    self.versions.destroy! if result
    result
  end

  include DataMapper::Has::Versions::InstanceMethods
end