mongo_mapper_acts_as_versioned 0.0.4 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ActsAsVersioned for [MongoMapper](http://github.com/jnunemaker/mongomapper)
2
2
 
3
- Basic MongoMapper port of technoweenie's [acts_as_versioned](http://github.com/technoweenie/acts_as_versioned). Stores changed attributes in a Hash key instead of copying all keys from the original model.
3
+ Basic MongoMapper port of technoweenie's [acts_as_versioned](http://github.com/technoweenie/acts_as_versioned). Stores changed attributes in a Hash key inside an Embedded Document instead of copying all keys from the original model.
4
4
 
5
5
  ## Usage
6
6
 
@@ -1,108 +1,55 @@
1
1
  module MongoMapper
2
2
  module Acts
3
3
  module Versioned
4
- VERSION = '0.0.4'
5
- CALLBACKS = [:set_new_version, :save_version, :save_version?]
4
+ VERSION = '0.0.10'
5
+ CALLBACKS = [:save_version, :save_version?]
6
6
 
7
7
  def self.configure(model)
8
8
  model.class_eval do
9
- cattr_accessor :versioned_class_name, :versioned_foreign_key,
10
- :versioned_collection_name, :non_versioned_keys
11
-
12
- self.versioned_class_name = :Version
13
- self.versioned_foreign_key = self.to_s.foreign_key
14
- self.versioned_collection_name = "#{collection_name.singularize}_versions"
15
- self.non_versioned_keys = [
16
- '_id', 'created_at', 'updated_at', 'creator_id',
17
- 'updater_id', 'version', versioned_foreign_key,
18
- '_type', '_version_type'
19
- ]
9
+ cattr_accessor :versioned_class_name, :non_versioned_keys
20
10
 
21
- const_set(versioned_class_name, Class.new).class_eval do
22
- include MongoMapper::Document
23
-
24
- class << self
25
- delegate :versioned_foreign_key, :to => :original_class
26
- end
27
-
28
- key :version, Integer
29
- key :changed_attributes, Hash
30
-
31
- if type_key = keys['_type']
32
- key :_version_type, type_key.type, type_key.options
33
- end
34
-
35
- def self.before(version)
36
- where(
37
- versioned_foreign_key => version[versioned_foreign_key],
38
- :version.lt => version.version
39
- ).sort(:version.desc).first
40
- end
41
-
42
- def self.after(version)
43
- where(
44
- versioned_foreign_key => version[versioned_foreign_key],
45
- :version.gt => version.version
46
- ).sort(:version.asc).first
47
- end
11
+ self.versioned_class_name = :Version
12
+ self.non_versioned_keys = %w(
13
+ _id _type created_at updated_at creator_id updater_id version
14
+ )
48
15
 
49
- def previous
50
- self.class.before(self)
51
- end
16
+ const_set(versioned_class_name, Class.new).class_eval do
17
+ include MongoMapper::EmbeddedDocument
52
18
 
53
- def next
54
- self.class.after(self)
55
- end
19
+ key :version, Integer
20
+ key :modified, Hash
56
21
  end
57
22
 
58
- versioned_class.cattr_accessor :original_class
59
- versioned_class.original_class = self
60
- versioned_class.set_collection_name versioned_collection_name
61
- versioned_class.belongs_to self.to_s.demodulize.underscore.to_sym,
62
- :class_name => self.to_s,
63
- :foreign_key => versioned_foreign_key
64
-
65
- key :version, Integer
66
-
67
- many :versions,
68
- :class_name => "#{self}::#{versioned_class_name}",
69
- :foreign_key => versioned_foreign_key,
70
- :dependent => :destroy do
71
- def earliest
72
- query.sort(:version).first
73
- end
74
-
75
- def latest
76
- query.sort(:version.desc).first
23
+ many :versions, :class => "#{self}::#{versioned_class_name}".constantize do
24
+ def [](given_version)
25
+ detect {|version| version.version.to_s == given_version.to_s }
77
26
  end
78
27
  end
79
-
80
- before_save :set_new_version
81
- after_save :save_version
82
28
  end
29
+
30
+ model.key :version, Integer
31
+ model.before_save :save_version
83
32
  end
84
33
 
85
34
  module InstanceMethods
86
35
  def save_version
87
- if @saving_version
88
- @saving_version = nil
89
-
36
+ if new_record? || save_version?
37
+ self.version = next_version
90
38
  rev = self.class.versioned_class.new
91
- clone_versioned_model(self, rev)
39
+ clone_attributes(self, rev)
92
40
  rev.version = version
93
- rev[self.class.versioned_foreign_key] = id
94
- rev.save!
41
+ self.versions << rev
95
42
  end
96
43
  end
97
44
 
98
45
  def revert_to(version)
99
46
  if version.is_a?(self.class.versioned_class)
100
- return false unless version[self.class.versioned_foreign_key] == id and !version.new_record?
47
+ return false if version.new_record?
101
48
  else
102
- return false unless version = versions.where(:version => version).first
49
+ return false unless version = versions[version]
103
50
  end
104
51
 
105
- clone_versioned_model(version, self)
52
+ clone_attributes(version, self)
106
53
  self.version = version.version
107
54
 
108
55
  true
@@ -125,17 +72,15 @@ module MongoMapper
125
72
  end
126
73
  end
127
74
 
128
- def clone_versioned_model(orig_model, new_model)
75
+ def clone_attributes(orig_model, new_model)
129
76
  if orig_model.is_a?(self.class.versioned_class)
130
- new_model['_type'] = orig_model['_version_type']
131
- orig_model = orig_model.changed_attributes
77
+ orig_model = orig_model.modified
132
78
  elsif new_model.is_a?(self.class.versioned_class)
133
- new_model['_version_type'] = orig_model['_type']
134
- new_model = new_model.changed_attributes
79
+ new_model = new_model.modified
135
80
  end
136
81
 
137
- self.class.versioned_keys.each do |col|
138
- new_model[col] = orig_model[col]
82
+ self.class.versioned_keys.each do |attribute|
83
+ new_model[attribute] = orig_model[attribute]
139
84
  end
140
85
  end
141
86
 
@@ -152,11 +97,6 @@ module MongoMapper
152
97
 
153
98
  protected
154
99
 
155
- def set_new_version
156
- @saving_version = new_record? || save_version?
157
- self.version = next_version if @saving_version
158
- end
159
-
160
100
  def next_version
161
101
  new_record? || versions.empty? ? 1 : versions.map(&:version).max.next
162
102
  end
@@ -1,231 +1,222 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe MongoMapper::Acts::Versioned do
4
- before :all do
5
- class Landmark
6
- include MongoMapper::Document
4
+ context 'landmarks and generally' do
5
+ before :all do
6
+ class Landmark
7
+ include MongoMapper::Document
7
8
 
8
- plugin MongoMapper::Acts::Versioned
9
+ plugin MongoMapper::Acts::Versioned
9
10
 
10
- self.non_versioned_keys << 'depth'
11
+ self.non_versioned_keys << 'depth'
11
12
 
12
- key :title, String
13
- key :depth, Integer
14
- timestamps!
13
+ key :title, String
14
+ key :depth, Integer
15
+ timestamps!
16
+ end
17
+
18
+ class Sublandmark < Landmark
19
+ key :location, String
20
+ end
15
21
  end
16
22
 
17
- class Sublandmark < Landmark
18
- key :location, String
23
+ it 'should set the correct properties on the version class' do
24
+ Landmark.versioned_class.should == Landmark::Version
25
+ Sublandmark.versioned_class.should == Landmark::Version
19
26
  end
20
- end
21
27
 
22
- it 'should set the correct properties on the version class' do
23
- Landmark::Version.original_class.should == Landmark
24
- Landmark::Version.collection_name.should == 'landmark_versions'
25
- Landmark.versioned_class.should == Landmark::Version
26
- Sublandmark::Version.original_class.should == Landmark
27
- Sublandmark::Version.collection_name.should == 'landmark_versions'
28
- Sublandmark.versioned_class.should == Landmark::Version
29
- end
28
+ it 'should save a versioned copy' do
29
+ l = Landmark.create(:title => 'title')
30
+ l.new_record?.should be_false
31
+ l.versions.size.should == 1
32
+ l.version.should == 1
33
+ l.versions.first.should be_a(Landmark.versioned_class)
34
+ end
30
35
 
31
- it 'should save a versioned copy' do
32
- l = Landmark.create(:title => 'title')
33
- l.new_record?.should be_false
34
- l.versions.size.should == 1
35
- l.version.should == 1
36
- l.versions.first.should be_a(Landmark.versioned_class)
37
- end
36
+ it 'should save without revision' do
37
+ l = Landmark.create(:title => 'title')
38
+ l.version.should == 1
38
39
 
39
- it 'should save without revision' do
40
- l = Landmark.create(:title => 'title')
41
- l.version.should == 1
40
+ l.update_attributes(:title => 'changed')
41
+ l = l.reload
42
+ l.version.should == 2
42
43
 
43
- l.update_attributes(:title => 'changed')
44
- l = l.reload
45
- l.version.should == 2
44
+ old_versions = l.versions.size
46
45
 
47
- old_versions = l.versions.size
46
+ l.save_without_revision
48
47
 
49
- l.save_without_revision
48
+ l.without_revision do
49
+ l.update_attributes :title => 'changed again'
50
+ end
50
51
 
51
- l.without_revision do
52
- l.update_attributes :title => 'changed again'
52
+ l.reload.versions.size.should == old_versions
53
53
  end
54
54
 
55
- l.reload.versions.size.should == old_versions
56
- end
55
+ it 'should rollback with version number' do
56
+ l = Landmark.create(:title => 'title')
57
+ (2..10).each do |i|
58
+ l = Landmark.first
59
+ l.update_attributes(:title => "title#{i}")
60
+ end
57
61
 
58
- it 'should rollback with version number' do
59
- l = Landmark.create(:title => 'title')
60
- (2..10).each do |i|
61
- l = Landmark.first
62
- l.update_attributes(:title => "title#{i}")
62
+ l = l.reload
63
+ l.version.should == 10
64
+ l.versions.size.should == 10
65
+ l.title.should == 'title10'
66
+
67
+ l.revert_to!(7).should be_true
68
+ l = l.reload
69
+ l.version.should == 7
70
+ l.versions.size.should == 10
71
+ l.title.should == 'title7'
63
72
  end
64
73
 
65
- l = l.reload
66
- l.version.should == 10
67
- l.versions.size.should == 10
68
- l.title.should == 'title10'
74
+ it 'should rollback with version class' do
75
+ l = Landmark.create(:title => 'title')
76
+ (2..10).each do |i|
77
+ l = Landmark.first
78
+ l.update_attributes(:title => "title#{i}")
79
+ end
69
80
 
70
- l.revert_to!(7).should be_true
71
- l = l.reload
72
- l.version.should == 7
73
- l.versions.size.should == 10
74
- l.title.should == 'title7'
75
- end
81
+ l = l.reload
82
+ l.version.should == 10
83
+ l.versions.size.should == 10
84
+ l.title.should == 'title10'
76
85
 
77
- it 'should rollback with version class' do
78
- l = Landmark.create(:title => 'title')
79
- (2..10).each do |i|
80
- l = Landmark.first
81
- l.update_attributes(:title => "title#{i}")
86
+ l.revert_to!(l.versions[7]).should be_true
87
+ l = l.reload
88
+ l.version.should == 7
89
+ l.versions.size.should == 10
90
+ l.title.should == 'title7'
82
91
  end
83
92
 
84
- l = l.reload
85
- l.version.should == 10
86
- l.versions.size.should == 10
87
- l.title.should == 'title10'
93
+ it 'should have versioned records belong to its parent' do
94
+ l = Landmark.create(:title => 'title')
95
+ (2..10).each do |i|
96
+ l = Landmark.first
97
+ l.update_attributes(:title => "title#{i}")
98
+ end
88
99
 
89
- l.revert_to!(l.versions.find_by_version(7)).should be_true
90
- l = l.reload
91
- l.version.should == 7
92
- l.versions.size.should == 10
93
- l.title.should == 'title7'
94
- end
100
+ l_version = l.reload.versions.last
101
+ l_version._root_document.should == l.reload
102
+ end
95
103
 
96
- it 'should have versioned records belong to its parent' do
97
- l = Landmark.create(:title => 'title')
98
- (2..10).each do |i|
99
- l = Landmark.first
100
- l.update_attributes(:title => "title#{i}")
104
+ it 'should not create new versions for skipped keys' do
105
+ l = Landmark.create(:title => 'title')
106
+ l.update_attributes(:depth => 1)
107
+ l = l.reload
108
+ l.version.should == 1
109
+ l.versions.size.should == 1
101
110
  end
102
111
 
103
- l_version = l.reload.versions.last
104
- l_version.landmark.should == l.reload
105
- end
112
+ it 'should create a new version even if a skipped key is added' do
113
+ l = Landmark.create(:title => 'title')
114
+ l.update_attributes(:title => 'new title', :depth => 1)
115
+ l = l.reload
116
+ l.version.should == 2
117
+ l.versions.size.should == 2
118
+ end
106
119
 
107
- it 'should not create new versions for skipped keys' do
108
- l = Landmark.create(:title => 'title')
109
- l.update_attributes(:depth => 1)
110
- l = l.reload
111
- l.version.should == 1
112
- l.versions.size.should == 1
113
- end
120
+ it 'should remember skipped keys through versions' do
121
+ l = Landmark.create(:title => 'title')
122
+ l.update_attributes(:title => 'new title')
123
+ l = l.reload
124
+ l.version.should == 2
125
+ l.versions.size.should == 2
126
+
127
+ l.update_attributes(:depth => 1)
128
+ l = l.reload
129
+ l.version.should == 2
130
+ l.versions.size.should == 2
131
+ l.depth.should == 1
132
+ l.title.should == 'new title'
133
+
134
+ l.revert_to!(1)
135
+ l = l.reload
136
+ l.version.should == 1
137
+ l.versions.size.should == 2
138
+ l.depth.should == 1
139
+ l.title.should == 'title'
140
+ end
114
141
 
115
- it 'should create a new version even if a skipped key is added' do
116
- l = Landmark.create(:title => 'title')
117
- l.update_attributes(:title => 'new title', :depth => 1)
118
- l = l.reload
119
- l.version.should == 2
120
- l.versions.size.should == 2
121
- end
142
+ it 'should store changes in a hash' do
143
+ l = Landmark.create(:title => 'title')
144
+ l.versions[1].modified.should == {'title' => 'title'}
122
145
 
123
- it 'should remember skipped keys through versions' do
124
- l = Landmark.create(:title => 'title')
125
- l.update_attributes(:title => 'new title')
126
- l = l.reload
127
- l.version.should == 2
128
- l.versions.size.should == 2
129
-
130
- l.update_attributes(:depth => 1)
131
- l = l.reload
132
- l.version.should == 2
133
- l.versions.size.should == 2
134
- l.depth.should == 1
135
- l.title.should == 'new title'
136
-
137
- l.revert_to!(1)
138
- l = l.reload
139
- l.version.should == 1
140
- l.versions.size.should == 2
141
- l.depth.should == 1
142
- l.title.should == 'title'
143
- end
146
+ l.update_attributes(:title => 'changed title', :depth => 1)
147
+ l.reload.versions[2].modified.should == {'title' => 'changed title'}
148
+ end
144
149
 
145
- it 'should store changes in a hash' do
146
- l = Landmark.create(:title => 'title')
147
- l.versions[0].changed_attributes.should == {'title' => 'title'}
150
+ it 'should save a versioned class with sci' do
151
+ s = Sublandmark.create!(:title => 'first title')
152
+ s.new_record?.should be_false
153
+ s.version.should == 1
148
154
 
149
- l.update_attributes(:title => 'changed title', :depth => 1)
150
- l.reload.versions[1].changed_attributes.should == {'title' => 'changed title'}
151
- end
155
+ s.versions.size.should == 1
156
+ s.versions.first.should be_a(Landmark.versioned_class)
157
+ s.versions.first._root_document.should == s
158
+ end
152
159
 
153
- context 'finders' do
154
- before :each do
155
- @l = Landmark.create(:title => 'title')
160
+ it 'should rollback with sci' do
161
+ l = Landmark.create(:title => 'other title')
156
162
  (2..5).each do |i|
157
- Landmark.first.update_attributes(:title => "title#{i}")
163
+ l = Landmark.first
164
+ l.update_attributes(:title => "other title#{i}")
158
165
  end
159
- @l = @l.reload
160
- end
161
-
162
- it 'should find the earliest version' do
163
- @l.versions.earliest.should == @l.versions.find_by_version(1)
164
- end
165
-
166
- it 'should find the latest version' do
167
- @l.versions.latest.should == @l.versions.find_by_version(5)
168
- end
169
166
 
170
- it 'should find the previous version' do
171
- @l.versions[1].previous.should == @l.versions[0]
172
- end
167
+ l = l.reload
168
+ l.version.should == 5
169
+ l.versions.size.should == 5
170
+ l.title.should == 'other title5'
171
+ l.revert_to!(3).should be_true
172
+ l = l.reload
173
+ l.version.should == 3
174
+ l.versions.size.should == 5
175
+ l.title.should == 'other title3'
176
+
177
+ s = Sublandmark.create(:title => 'title')
178
+ (2..5).each do |i|
179
+ s = Sublandmark.first
180
+ s.update_attributes(:title => "title#{i}")
181
+ end
173
182
 
174
- it 'should find the next version' do
175
- @l.versions[0].next.should == @l.versions[1]
183
+ s = s.reload
184
+ s.versions.should_not == l.versions
185
+ s.version.should == 5
186
+ s.versions.size.should == 5
187
+ s.title.should == 'title5'
188
+ s.revert_to!(3).should be_true
189
+ s = s.reload
190
+ s.version.should == 3
191
+ s.versions.size.should == 5
192
+ s.title.should == 'title3'
176
193
  end
177
194
  end
178
195
 
179
- it 'should save a versioned class with sci' do
180
- s = Sublandmark.create!(:title => 'first title')
181
- s.new_record?.should be_false
182
- s.version.should == 1
196
+ context 'nodes' do
197
+ before :all do
198
+ class Node
199
+ include MongoMapper::Document
183
200
 
184
- s.versions.size.should == 1
185
- s.versions.first.should be_a(Landmark.versioned_class)
186
- s.versions.first.attributes.keys.should include('_version_type')
187
- s.versions.first._version_type.should == 'Sublandmark'
188
- s.versions.first.landmark.should == s
189
- end
201
+ key :title, String
202
+ end
190
203
 
191
- it 'should rollback with sti' do
192
- s = Sublandmark.create(:title => 'title')
193
- (2..5).each do |i|
194
- s = Sublandmark.first
195
- s.update_attributes(:title => "title#{i}")
196
- end
204
+ class Page < Node
205
+ plugin MongoMapper::Acts::Versioned
206
+ end
197
207
 
198
- s = s.reload
199
- s.version.should == 5
200
- s.versions.size.should == 5
201
- s.title.should == 'title5'
202
- s.revert_to!(3).should be_true
203
- s = s.reload
204
- s.version.should == 3
205
- s.versions.size.should == 5
206
- s.title.should == 'title3'
207
-
208
- s.versions.each do |version|
209
- version._version_type.should == 'Sublandmark'
208
+ class Post < Node
209
+ plugin MongoMapper::Acts::Versioned
210
+ end
210
211
  end
211
212
 
212
- l = Landmark.create(:title => 'other title')
213
- (2..5).each do |i|
214
- l = Landmark.first
215
- l.update_attributes(:title => "other title#{i}")
213
+ it 'should version only the subclass' do
214
+ page = Page.create(:title => 'page title')
215
+ post = Post.create(:title => 'post title')
216
+ page.version.should == 1
217
+ page.versions.size.should == 1
218
+ post.version.should == 1
219
+ post.versions.size.should == 1
216
220
  end
217
-
218
- l = l.reload
219
- l.versions.should_not == s.versions
220
- l.version.should == 5
221
- l.versions.size.should == 5
222
- l.title.should == 'other title5'
223
- l.revert_to!(3).should be_true
224
- l = l.reload
225
- l.version.should == 3
226
- l.versions.size.should == 5
227
- l.title.should == 'other title3'
228
-
229
- Landmark::Version.count.should == 10
230
221
  end
231
222
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 4
9
- version: 0.0.4
8
+ - 10
9
+ version: 0.0.10
10
10
  platform: ruby
11
11
  authors:
12
12
  - Gigamo
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-08-27 00:00:00 +02:00
17
+ date: 2010-09-12 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency