mongo_mapper_acts_as_versioned 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +5 -1
- data/lib/acts_as_versioned.rb +150 -146
- data/lib/acts_as_versioned/version.rb +6 -2
- data/spec/acts_as_versioned_spec.rb +2 -2
- metadata +2 -2
data/README.md
CHANGED
@@ -9,7 +9,7 @@ Basic MongoMapper port of technoweenie's [acts_as_versioned](http://github.com/t
|
|
9
9
|
class Page
|
10
10
|
include MongoMapper::Document
|
11
11
|
|
12
|
-
plugin
|
12
|
+
plugin MongoMapper::Acts::Versioned
|
13
13
|
|
14
14
|
key :title, String
|
15
15
|
end
|
@@ -60,6 +60,10 @@ Simply add `self.skipped_keys << 'new_skipped_key'` somewhere in your model.
|
|
60
60
|
* Properly document those options
|
61
61
|
* Support SCI
|
62
62
|
|
63
|
+
## Bundler note
|
64
|
+
|
65
|
+
Make sure to specify `:require => 'acts_as_versioned'` in your Gemfile.
|
66
|
+
|
63
67
|
## Copyright
|
64
68
|
|
65
69
|
Copyright (c) 2010 Gigamo <gigamo@gmail.com>. See LICENSE for details.
|
data/lib/acts_as_versioned.rb
CHANGED
@@ -1,178 +1,182 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module MongoMapper
|
2
|
+
module Acts
|
3
|
+
module Versioned
|
4
|
+
CALLBACKS = [:set_new_version, :save_version, :save_version?]
|
5
|
+
|
6
|
+
def self.configure(model)
|
7
|
+
model.class_eval do
|
8
|
+
const_set(:Version, Class.new).class_eval do
|
9
|
+
include MongoMapper::Document
|
10
|
+
|
11
|
+
key :version, Integer
|
12
|
+
key :changed_attributes, Hash
|
13
|
+
|
14
|
+
def self.before(version)
|
15
|
+
where(
|
16
|
+
super_foreign_key => version[super_foreign_key],
|
17
|
+
:version.lt => version.version
|
18
|
+
).sort(:version.desc).first
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.after(version)
|
22
|
+
where(
|
23
|
+
super_foreign_key => version[super_foreign_key],
|
24
|
+
:version.gt => version.version
|
25
|
+
).sort(:version.asc).first
|
26
|
+
end
|
27
|
+
|
28
|
+
def previous
|
29
|
+
self.class.before(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def next
|
33
|
+
self.class.after(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.super_foreign_key
|
37
|
+
original_class.to_s.foreign_key
|
38
|
+
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
protected :super_foreign_key
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
versioned_class.cattr_accessor :original_class
|
46
|
+
versioned_class.original_class = self
|
47
|
+
versioned_class.set_collection_name "#{self.collection_name.singularize}_versions"
|
48
|
+
versioned_class.belongs_to self.to_s.demodulize.underscore.to_sym,
|
49
|
+
:class_name => "::#{self}",
|
50
|
+
:foreign_key => self.to_s.foreign_key
|
51
|
+
end
|
8
52
|
|
9
|
-
key :version,
|
10
|
-
|
53
|
+
model.key :version, Integer
|
54
|
+
model.many :versions, :class_name => "#{model}::Version",
|
55
|
+
:foreign_key => model.to_s.foreign_key, :dependent => :destroy do
|
56
|
+
def earliest
|
57
|
+
query.sort(:version).first
|
58
|
+
end
|
11
59
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
:version.lt => version.version
|
16
|
-
).sort(:version.desc).first
|
60
|
+
def latest
|
61
|
+
query.sort(:version.desc).first
|
62
|
+
end
|
17
63
|
end
|
64
|
+
model.before_save :set_new_version
|
65
|
+
model.after_save :save_version
|
66
|
+
end
|
18
67
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
68
|
+
module InstanceMethods
|
69
|
+
def save_version
|
70
|
+
if @saving_version
|
71
|
+
@saving_version = nil
|
72
|
+
|
73
|
+
rev = self.class.versioned_class.new
|
74
|
+
clone_versioned_model(self, rev)
|
75
|
+
rev.version = version
|
76
|
+
rev[self.class.to_s.foreign_key] = id
|
77
|
+
rev.save!
|
78
|
+
end
|
24
79
|
end
|
25
80
|
|
26
|
-
def
|
27
|
-
self.class.
|
28
|
-
|
81
|
+
def revert_to(version)
|
82
|
+
if version.is_a?(self.class.versioned_class)
|
83
|
+
return false unless version[self.class.to_s.foreign_key] == id and !version.new_record?
|
84
|
+
else
|
85
|
+
return false unless version = versions.where(:version => version).first
|
86
|
+
end
|
29
87
|
|
30
|
-
|
31
|
-
self.
|
32
|
-
end
|
88
|
+
clone_versioned_model(version, self)
|
89
|
+
self.version = version.version
|
33
90
|
|
34
|
-
|
35
|
-
original_class.to_s.foreign_key
|
91
|
+
true
|
36
92
|
end
|
37
93
|
|
38
|
-
|
39
|
-
|
94
|
+
def revert_to!(version)
|
95
|
+
revert_to(version) ? save_without_revision : false
|
40
96
|
end
|
41
|
-
end
|
42
|
-
|
43
|
-
versioned_class.cattr_accessor :original_class
|
44
|
-
versioned_class.original_class = self
|
45
|
-
versioned_class.set_collection_name "#{self.collection_name.singularize}_versions"
|
46
|
-
versioned_class.belongs_to self.to_s.demodulize.underscore.to_sym,
|
47
|
-
:class_name => "::#{self}",
|
48
|
-
:foreign_key => self.to_s.foreign_key
|
49
|
-
end
|
50
|
-
|
51
|
-
model.key :version, Integer
|
52
|
-
model.many :versions, :class_name => "#{model}::Version",
|
53
|
-
:foreign_key => model.to_s.foreign_key, :dependent => :destroy do
|
54
|
-
def earliest
|
55
|
-
query.sort(:version).first
|
56
|
-
end
|
57
|
-
|
58
|
-
def latest
|
59
|
-
query.sort(:version.desc).first
|
60
|
-
end
|
61
|
-
end
|
62
|
-
model.before_save :set_new_version
|
63
|
-
model.after_save :save_version
|
64
|
-
end
|
65
97
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
98
|
+
def save_without_revision
|
99
|
+
save_without_revision!
|
100
|
+
true
|
101
|
+
rescue
|
102
|
+
false
|
103
|
+
end
|
70
104
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
end
|
105
|
+
def save_without_revision!
|
106
|
+
without_revision do
|
107
|
+
save!
|
108
|
+
end
|
109
|
+
end
|
78
110
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
return false unless version = versions.where(:version => version).first
|
84
|
-
end
|
111
|
+
def clone_versioned_model(orig_model, new_model)
|
112
|
+
if orig_model.is_a?(self.class.versioned_class)
|
113
|
+
orig_model = orig_model.changed_attributes
|
114
|
+
end
|
85
115
|
|
86
|
-
|
87
|
-
|
116
|
+
if new_model.is_a?(self.class.versioned_class)
|
117
|
+
new_model = new_model.changed_attributes
|
118
|
+
end
|
88
119
|
|
89
|
-
|
90
|
-
|
120
|
+
self.class.versioned_keys.each do |col|
|
121
|
+
new_model[col] = orig_model[col]
|
122
|
+
end
|
123
|
+
end
|
91
124
|
|
92
|
-
|
93
|
-
|
94
|
-
|
125
|
+
def save_version?
|
126
|
+
(self.class.versioned_keys & changed).any?
|
127
|
+
end
|
95
128
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
rescue
|
100
|
-
false
|
101
|
-
end
|
129
|
+
def without_revision(&block)
|
130
|
+
self.class.without_revision(&block)
|
131
|
+
end
|
102
132
|
|
103
|
-
|
104
|
-
|
105
|
-
save!
|
106
|
-
end
|
107
|
-
end
|
133
|
+
def empty_callback
|
134
|
+
end
|
108
135
|
|
109
|
-
|
110
|
-
if orig_model.is_a?(self.class.versioned_class)
|
111
|
-
orig_model = orig_model.changed_attributes
|
112
|
-
end
|
136
|
+
protected
|
113
137
|
|
114
|
-
|
115
|
-
|
116
|
-
|
138
|
+
def set_new_version
|
139
|
+
@saving_version = new_record? || save_version?
|
140
|
+
self.version = next_version if @saving_version
|
141
|
+
end
|
117
142
|
|
118
|
-
|
119
|
-
|
143
|
+
def next_version
|
144
|
+
(new_record? ? 0 : versions.map(&:version).max) + 1
|
145
|
+
end
|
120
146
|
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def save_version?
|
124
|
-
(self.class.versioned_keys & changed).any?
|
125
|
-
end
|
126
|
-
|
127
|
-
def without_revision(&block)
|
128
|
-
self.class.without_revision(&block)
|
129
|
-
end
|
130
|
-
|
131
|
-
def empty_callback
|
132
|
-
end
|
133
|
-
|
134
|
-
protected
|
135
147
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
def next_version
|
142
|
-
(new_record? ? 0 : versions.map(&:version).max) + 1
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
module ClassMethods
|
147
|
-
def versioned_class
|
148
|
-
const_get(:Version)
|
149
|
-
end
|
148
|
+
module ClassMethods
|
149
|
+
def versioned_class
|
150
|
+
const_get(:Version)
|
151
|
+
end
|
150
152
|
|
151
|
-
|
152
|
-
|
153
|
-
|
153
|
+
def versioned_keys
|
154
|
+
keys.keys - skipped_keys
|
155
|
+
end
|
154
156
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
157
|
+
def without_revision
|
158
|
+
class_eval do
|
159
|
+
CALLBACKS.each do |attr_name|
|
160
|
+
alias_method :"orig_#{attr_name}", attr_name
|
161
|
+
alias_method attr_name, :empty_callback
|
162
|
+
end
|
163
|
+
end
|
164
|
+
yield
|
165
|
+
ensure
|
166
|
+
class_eval do
|
167
|
+
CALLBACKS.each do |attr_name|
|
168
|
+
alias_method attr_name, :"orig_#{attr_name}"
|
169
|
+
end
|
170
|
+
end
|
160
171
|
end
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
172
|
+
|
173
|
+
def skipped_keys
|
174
|
+
@skipped_keys ||= [
|
175
|
+
'_id', 'created_at', 'updated_at', 'creator_id',
|
176
|
+
'updater_id', 'version', self.class.to_s.foreign_key
|
177
|
+
]
|
167
178
|
end
|
168
179
|
end
|
169
180
|
end
|
170
|
-
|
171
|
-
def skipped_keys
|
172
|
-
@skipped_keys ||= [
|
173
|
-
'_id', 'created_at', 'updated_at', 'creator_id',
|
174
|
-
'updater_id', 'version', self.class.to_s.foreign_key
|
175
|
-
]
|
176
|
-
end
|
177
181
|
end
|
178
182
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe MongoMapper::Acts::Versioned do
|
4
4
|
before :all do
|
5
5
|
class Landmark
|
6
6
|
include MongoMapper::Document
|
7
7
|
|
8
|
-
plugin
|
8
|
+
plugin MongoMapper::Acts::Versioned
|
9
9
|
|
10
10
|
self.skipped_keys << 'depth'
|
11
11
|
|