mongoid_versioning 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1541712ab768cbdfe3e5feff620d363e15f26c36
4
+ data.tar.gz: 502a9f2582215937f32dc231a1bfe92bebe4d68f
5
+ SHA512:
6
+ metadata.gz: b36237f72a53a2d07d660c65a3bcfa67e41c9d665b6a4e8616795f070f44be2c06cdc41f6306b02650612afd5407ecc179c615a8e43cfe5f8b6eada0744794f6
7
+ data.tar.gz: 73460dbb43b06e4235288c944ac2d1d62411d726bab2afedeb7fd5136528018f6aaf2b6a4bce9f2ab8201075b507339da1cc13a93c42983c88ff3f4c84d80439
data/.gitignore ADDED
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ sudo: false
2
+ language: ruby
3
+ cache: bundler
4
+ script: 'bundle exec rake'
5
+ rvm:
6
+ - 2.1.2
7
+ services:
8
+ - mongodb
9
+
10
+ notifications:
11
+ email:
12
+ recipients:
13
+ - tomas.celizna@gmail.com
14
+ on_failure: change
15
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mongoid_permalink_extension.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,106 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mongoid_versioning (0.0.1)
5
+ mongoid (~> 4.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (4.1.6)
11
+ activesupport (= 4.1.6)
12
+ builder (~> 3.1)
13
+ activesupport (4.1.6)
14
+ i18n (~> 0.6, >= 0.6.9)
15
+ json (~> 1.7, >= 1.7.7)
16
+ minitest (~> 5.1)
17
+ thread_safe (~> 0.1)
18
+ tzinfo (~> 1.1)
19
+ bson (2.3.0)
20
+ builder (3.2.2)
21
+ celluloid (0.16.0)
22
+ timers (~> 4.0.0)
23
+ coderay (1.1.0)
24
+ connection_pool (2.0.0)
25
+ coveralls (0.7.1)
26
+ multi_json (~> 1.3)
27
+ rest-client
28
+ simplecov (>= 0.7)
29
+ term-ansicolor
30
+ thor
31
+ database_cleaner (1.3.0)
32
+ docile (1.1.5)
33
+ ffi (1.9.5)
34
+ formatador (0.2.5)
35
+ guard (2.6.1)
36
+ formatador (>= 0.2.4)
37
+ listen (~> 2.7)
38
+ lumberjack (~> 1.0)
39
+ pry (>= 0.9.12)
40
+ thor (>= 0.18.1)
41
+ guard-minitest (2.3.2)
42
+ guard (~> 2.0)
43
+ minitest (>= 3.0)
44
+ hitimes (1.2.2)
45
+ i18n (0.6.11)
46
+ json (1.8.1)
47
+ listen (2.7.11)
48
+ celluloid (>= 0.15.2)
49
+ rb-fsevent (>= 0.9.3)
50
+ rb-inotify (>= 0.9)
51
+ lumberjack (1.0.9)
52
+ method_source (0.8.2)
53
+ mime-types (2.4.1)
54
+ minitest (5.4.2)
55
+ mongoid (4.0.0)
56
+ activemodel (~> 4.0)
57
+ moped (~> 2.0.0)
58
+ origin (~> 2.1)
59
+ tzinfo (>= 0.3.37)
60
+ moped (2.0.0)
61
+ bson (~> 2.2)
62
+ connection_pool (~> 2.0)
63
+ optionable (~> 0.2.0)
64
+ multi_json (1.10.1)
65
+ netrc (0.7.7)
66
+ optionable (0.2.0)
67
+ origin (2.1.1)
68
+ pry (0.10.1)
69
+ coderay (~> 1.1.0)
70
+ method_source (~> 0.8.1)
71
+ slop (~> 3.4)
72
+ rake (10.3.2)
73
+ rb-fsevent (0.9.4)
74
+ rb-inotify (0.9.5)
75
+ ffi (>= 0.5.0)
76
+ rest-client (1.7.2)
77
+ mime-types (>= 1.16, < 3.0)
78
+ netrc (~> 0.7)
79
+ simplecov (0.9.1)
80
+ docile (~> 1.1.0)
81
+ multi_json (~> 1.0)
82
+ simplecov-html (~> 0.8.0)
83
+ simplecov-html (0.8.0)
84
+ slop (3.6.0)
85
+ term-ansicolor (1.3.0)
86
+ tins (~> 1.0)
87
+ thor (0.19.1)
88
+ thread_safe (0.3.4)
89
+ timers (4.0.1)
90
+ hitimes
91
+ tins (1.3.3)
92
+ tzinfo (1.2.2)
93
+ thread_safe (~> 0.1)
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ bundler (~> 1.3)
100
+ coveralls
101
+ database_cleaner
102
+ guard
103
+ guard-minitest
104
+ minitest
105
+ mongoid_versioning!
106
+ rake
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :minitest do
5
+ watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
6
+ watch(%r{^test/.+_test\.rb$})
7
+ watch(%r{^test/test_helper\.rb$}) { 'test' }
8
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Tomas Celizna
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Mongoid Versioning
2
+
3
+ [![Build Status](https://travis-ci.org/tomasc/mongoid_versioning.svg)](https://travis-ci.org/tomasc/mongoid_versioning) [![Gem Version](https://badge.fury.io/rb/mongoid_versioning.svg)](http://badge.fury.io/rb/mongoid_versioning) [![Coverage Status](https://img.shields.io/coveralls/tomasc/mongoid_versioning.svg)](https://coveralls.io/r/tomasc/mongoid_versioning)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mongoid_versioning'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```
22
+ $ gem install mongoid_versioning
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ Include the `MongoidVersioning::Versioned` module into your model:
28
+
29
+ ```ruby
30
+ class MyVersionedDocument
31
+ include Mongoid::Document
32
+ include MongoidVersioning::Versioned
33
+ end
34
+ ```
35
+
36
+ Your class will then have:
37
+
38
+ ```ruby
39
+ field :_version, type: Integer
40
+ field :_based_on_version, type: Integer
41
+ ```
42
+
43
+ ### Creating versions
44
+
45
+ To create new version of your document:
46
+
47
+ ```ruby
48
+ doc = MyVersionedDocument.new
49
+ doc.revise # => true
50
+ doc._version # => 1
51
+ doc._based_on_version # => nil
52
+ ```
53
+
54
+ The `#revise` method validates the document and runs `:revise`, `:save` and `:update` callbacks (resp. `:revise`, `:save` and `:create` for new record).
55
+
56
+ ### Retrieving versions
57
+
58
+ To access all previous versions:
59
+
60
+ ```ruby
61
+ doc.previous_versions # => Mongoid::Criteria
62
+ ```
63
+
64
+ These versions are stored in separate collection, by default named by appending `.versions` to name of the source collection. In the above example it is `my_versioned_documents.versions`.
65
+
66
+ To access latest version (as stored in the db):
67
+
68
+ ```ruby
69
+ doc.latest_version # => MyVersionedDocument
70
+ ```
71
+
72
+ To retrieve all versions of a document:
73
+
74
+ ```ruby
75
+ doc.versions # => Array
76
+ ```
77
+
78
+ To retrieve specific version:
79
+
80
+ ```ruby
81
+ doc.version(2) # => MyVersionedDocument
82
+ ```
83
+
84
+ ## Further Reading
85
+
86
+ See [Further Thoughts on How to Track Versions with MongoDB](http://askasya.com/post/revisitversions).
87
+
88
+ ## Contributing
89
+
90
+ 1. Fork it ( https://github.com/tomasc/mongoid_versioning/fork )
91
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
92
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
93
+ 4. Push to the branch (`git push origin my-new-feature`)
94
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = 'test/**/*_test.rb'
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,3 @@
1
+ module MongoidVersioning
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,123 @@
1
+ module MongoidVersioning
2
+ module Versioned
3
+
4
+ def self.included base
5
+ base.extend ClassMethods
6
+ base.class_eval do
7
+ define_model_callbacks :revise, only: [:before, :after]
8
+
9
+ field :_version, type: Integer
10
+ field :_based_on_version, type: Integer
11
+
12
+ collection.database[versions_collection_name].indexes.create(
13
+ { _orig_id: 1, _version: 1 }, { unique: true }
14
+ )
15
+
16
+ after_initialize :revert_id
17
+ end
18
+ end
19
+
20
+ # =====================================================================
21
+
22
+ module ClassMethods
23
+ def versions_collection_name
24
+ [collection.name, 'versions'].join('.')
25
+ end
26
+ end
27
+
28
+ # =====================================================================
29
+
30
+ def revise options={}
31
+ if new_record?
32
+ !_create_revised(options).new_record?
33
+ else
34
+ _update_revised(options)
35
+ end
36
+ end
37
+
38
+ # ---------------------------------------------------------------------
39
+
40
+ def versions
41
+ [latest_version].concat(previous_versions)
42
+ end
43
+
44
+ def latest_version
45
+ self.class.where(_id: id).first
46
+ end
47
+
48
+ def previous_versions
49
+ self.class.with(collection: self.class.versions_collection_name).
50
+ where(_orig_id: id).
51
+ lt(_version: _version).
52
+ desc(:_version)
53
+ end
54
+
55
+ def version v
56
+ return latest_version if v == _version
57
+ previous_versions.where(_version: v).first
58
+ end
59
+
60
+ private # =============================================================
61
+
62
+ def revert_id
63
+ return unless self['_orig_id']
64
+ self._id = self['_orig_id']
65
+ end
66
+
67
+ # these mirror the #create and #save methods from Mongoid
68
+ def _create_revised options={}
69
+ return self if performing_validations?(options) && invalid?(:create)
70
+ result = run_callbacks(:revise) do
71
+ run_callbacks(:save) do
72
+ run_callbacks(:create) do
73
+ _revise
74
+ true
75
+ end
76
+ end
77
+ end
78
+ post_process_persist(result, options) and self
79
+ end
80
+
81
+ def _update_revised options={}
82
+ return false if performing_validations?(options) && invalid?(:update)
83
+ process_flagged_destroys
84
+ result = run_callbacks(:revise) do
85
+ run_callbacks(:save) do
86
+ run_callbacks(:update) do
87
+ _revise
88
+ true
89
+ end
90
+ end
91
+ end
92
+ post_process_persist(result, options) and self
93
+ end
94
+
95
+ def _revise
96
+ previous_version = nil
97
+
98
+ # 1. get the latest version as stored in the db
99
+ if previous_doc = self.class.collection.find({ _id: id }).first
100
+
101
+ previous_version = previous_doc["_version"] || 1
102
+
103
+ previous_doc['_orig_id'] = previous_doc['_id']
104
+ previous_doc['_id'] = BSON::ObjectId.new
105
+ previous_doc['_version'] = previous_version
106
+
107
+ # 2. upsert the latest version into the .versions collection
108
+ self.class.collection.database[self.class.versions_collection_name].where(_orig_id: id, _version: previous_version).upsert(previous_doc)
109
+ end
110
+
111
+ # 3. insert new version
112
+ self._based_on_version = _version || previous_version
113
+ self._version = previous_version.to_i+1
114
+
115
+ self.class.collection.where(_id: id).upsert(self.as_document)
116
+
117
+ # TODO
118
+ # if (result.nModified != 1) {
119
+ # print("Someone got there first, replay flow to try again");
120
+ # }
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,5 @@
1
+ # http://askasya.com/post/revisitversions
2
+
3
+ require "mongoid_versioning/version"
4
+
5
+ require "mongoid_versioning/versioned"
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mongoid_versioning/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mongoid_versioning"
8
+ spec.version = MongoidVersioning::VERSION
9
+ spec.authors = ["Tomas Celizna"]
10
+ spec.email = ["tomas.celizna@gmail.com"]
11
+ spec.description = %q{Versioning Mongoid documents by means of separate collection.}
12
+ spec.summary = %q{Versioning Mongoid documents by means of separate collection.}
13
+ spec.homepage = "https://github.com/tomasc/mongoid_versioning"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "mongoid", "~> 4.0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "coveralls"
25
+ spec.add_development_dependency "database_cleaner"
26
+ spec.add_development_dependency "guard"
27
+ spec.add_development_dependency "guard-minitest"
28
+ spec.add_development_dependency "minitest"
29
+ spec.add_development_dependency "rake"
30
+ end
@@ -0,0 +1,299 @@
1
+ require 'test_helper'
2
+
3
+ class TestDocument
4
+ include Mongoid::Document
5
+ include MongoidVersioning::Versioned
6
+
7
+ attr_accessor :callbacks
8
+
9
+ field :name, type: String
10
+
11
+ validates :name, presence: true
12
+
13
+ before_revise -> i { i.callbacks = i.callbacks << 'before_revise' }
14
+ after_revise -> i { i.callbacks = i.callbacks << 'after_revise' }
15
+ before_save -> i { i.callbacks = i.callbacks << 'before_save' }
16
+ after_save -> i { i.callbacks = i.callbacks << 'after_save' }
17
+ before_update -> i { i.callbacks = i.callbacks << 'before_update' }
18
+ after_update -> i { i.callbacks = i.callbacks << 'after_update' }
19
+ before_create -> i { i.callbacks = i.callbacks << 'before_create' }
20
+ after_create -> i { i.callbacks = i.callbacks << 'after_create' }
21
+
22
+ def callbacks
23
+ @callbacks ||= []
24
+ end
25
+ end
26
+
27
+ module MongoidVersioning
28
+ describe Versioned do
29
+
30
+ subject { TestDocument.new(name: 'Init') }
31
+
32
+ # =====================================================================
33
+
34
+ describe 'fields' do
35
+ it 'has :_version' do
36
+ subject.must_respond_to :_version
37
+ end
38
+
39
+ it 'has :_based_on_version' do
40
+ subject.must_respond_to :_based_on_version
41
+ end
42
+ end
43
+
44
+ # =====================================================================
45
+
46
+ describe 'class methods' do
47
+ describe '.versions_collection_name' do
48
+ it 'infers name for version collection' do
49
+ subject.class.versions_collection_name.must_equal "#{subject.collection.name}.versions"
50
+ end
51
+ end
52
+ end
53
+
54
+ # =====================================================================
55
+
56
+ describe 'instance methods' do
57
+ describe '#revise' do
58
+
59
+ describe 'when invalid' do
60
+ let(:invalid_document) { TestDocument.new }
61
+
62
+ it 'returns false' do
63
+ invalid_document.revise.must_equal false
64
+ end
65
+ end
66
+
67
+ describe 'new record' do
68
+ before do
69
+ subject.callbacks = []
70
+ subject.revise
71
+
72
+ @current_docs = TestDocument.collection.where({ _id: subject.id })
73
+ @version_docs = TestDocument.collection.database[TestDocument.versions_collection_name].where(_orig_id: subject.id)
74
+ end
75
+
76
+ describe 'callbacks' do
77
+ it 'runs :revise, :save, :create' do
78
+ subject.callbacks.must_equal %w(before_revise before_save before_create after_create after_save after_revise)
79
+ end
80
+ end
81
+
82
+ describe 'default collection' do
83
+ it 'stores the document' do
84
+ @current_docs.first.must_be :present?
85
+ end
86
+ it '_version to 1' do
87
+ @current_docs.first['_version'].must_equal 1
88
+ end
89
+ it '_based_on_version at nil' do
90
+ @current_docs.first['_based_on_version'].must_be_nil
91
+ end
92
+ it 'maintains only one current doc' do
93
+ @current_docs.count.must_equal 1
94
+ end
95
+ end
96
+
97
+ describe 'versions' do
98
+ it 'does not create any versions' do
99
+ @version_docs.count.must_equal 0
100
+ end
101
+ end
102
+ end
103
+
104
+ # ---------------------------------------------------------------------
105
+
106
+ describe 'existing record' do
107
+ let(:existing_document) { TestDocument.create(name: 'Init') }
108
+
109
+ before do
110
+ existing_document.callbacks = []
111
+ existing_document.name = 'Foo'
112
+ existing_document.revise
113
+
114
+ @current_docs = TestDocument.collection.where(_id: existing_document.id)
115
+ @version_docs = TestDocument.collection.database[TestDocument.versions_collection_name].where(_orig_id: existing_document.id)
116
+ end
117
+
118
+ describe 'callbacks' do
119
+ it 'runs :revise, :save, :update' do
120
+ existing_document.callbacks.must_equal %w(before_revise before_save before_update after_update after_save after_revise)
121
+ end
122
+ end
123
+
124
+ describe 'default collection' do
125
+ it 'updates the document' do
126
+ @current_docs.first['name'].must_equal 'Foo'
127
+ end
128
+ it '_version to 2' do
129
+ @current_docs.first['_version'].must_equal 2
130
+ end
131
+ it 'sets the _based_on_version to 1' do
132
+ @current_docs.first['_based_on_version'].must_equal 1
133
+ end
134
+ it 'maintains only one current doc' do
135
+ @current_docs.count.must_equal 1
136
+ end
137
+ end
138
+
139
+ describe 'previous versions' do
140
+ it 'copies the latest version to .versions' do
141
+ @version_docs.first.must_be :present?
142
+ end
143
+
144
+ it '_version to 1' do
145
+ @version_docs.first['_version'].must_equal 1
146
+ end
147
+ it '_version to 1' do
148
+ @version_docs.first['_based_on_version'].must_equal nil
149
+ end
150
+ it 'is not updated' do
151
+ @version_docs.first['name'].wont_equal 'Foo'
152
+ end
153
+ it 'creates only one version' do
154
+ @version_docs.count.must_equal 1
155
+ end
156
+ end
157
+ end
158
+
159
+ # ---------------------------------------------------------------------
160
+
161
+ describe 'subsequent revision' do
162
+ before do
163
+ subject.name = 'v1'
164
+ subject.revise
165
+ subject.name = 'v2'
166
+ subject.revise
167
+ subject.name = 'v3'
168
+ subject.revise
169
+
170
+ @current_docs = TestDocument.collection.where(_id: subject.id)
171
+ @version_docs = TestDocument.collection.database[TestDocument.versions_collection_name].where(_orig_id: subject.id)
172
+ end
173
+
174
+ describe 'default collection' do
175
+ it 'updates the current document in the db' do
176
+ @current_docs.first['name'].must_equal 'v3'
177
+ @current_docs.first['_version'].must_equal 3
178
+ @current_docs.first['_based_on_version'].must_equal 2
179
+ @current_docs.count.must_equal 1
180
+ end
181
+ end
182
+
183
+ describe 'versions' do
184
+ it 'has 2 previous versions' do
185
+ @version_docs.count.must_equal 2
186
+ @version_docs.collect{ |i| i['_version'] }.must_equal [1,2]
187
+ @version_docs.collect{ |i| i['_based_on_version'] }.must_equal [nil,1]
188
+ end
189
+ end
190
+ end
191
+
192
+ # ---------------------------------------------------------------------
193
+
194
+ describe 'revise on previous version' do
195
+ before do
196
+ subject.name = 'v1'
197
+ subject.revise
198
+ subject.name = 'v2'
199
+ subject.revise
200
+ subject.name = 'v3'
201
+ subject.revise
202
+
203
+ @new_version = subject.version(1)
204
+ @new_version.revise
205
+ end
206
+
207
+ it 'saves reverted attribute' do
208
+ @new_version.name.must_equal 'v1'
209
+ end
210
+ it 'updates :_version' do
211
+ @new_version._version.must_equal 4
212
+ end
213
+ it 'updates :_based_on_version' do
214
+ @new_version._based_on_version.must_equal 1
215
+ end
216
+ end
217
+ end
218
+
219
+ # =====================================================================
220
+
221
+ describe 'versions' do
222
+ before do
223
+ subject.name = 'v1'
224
+ subject.revise
225
+ subject.name = 'v2'
226
+ subject.revise
227
+ subject.name = 'v3'
228
+ subject.revise
229
+ subject.name = 'Foo'
230
+ end
231
+
232
+ it 'returns an Array' do
233
+ subject.versions.must_be_kind_of Array
234
+ end
235
+
236
+ # ---------------------------------------------------------------------
237
+
238
+ describe '#previous_versions' do
239
+ it 'returns everything but the latest' do
240
+ subject.previous_versions.map(&:_version).must_equal [2,1]
241
+ end
242
+ it 'correctly reverts document _ids' do
243
+ subject.previous_versions.map(&:id).uniq.must_equal [subject.id]
244
+ end
245
+ end
246
+
247
+ # ---------------------------------------------------------------------
248
+
249
+ describe '#latest_version' do
250
+ it 'includes the latest version as in the database' do
251
+ subject.latest_version.name.wont_equal 'Foo'
252
+ end
253
+ end
254
+
255
+ # ---------------------------------------------------------------------
256
+
257
+ describe '#versions' do
258
+ it 'returns all versions including the latest one' do
259
+ subject.versions.map(&:_version).must_equal [3,2,1]
260
+ end
261
+ end
262
+
263
+
264
+ # ---------------------------------------------------------------------
265
+
266
+ describe '#version' do
267
+ before do
268
+ subject.name = 'v1'
269
+ subject.revise
270
+ subject.name = 'v2'
271
+ subject.revise
272
+ subject.name = 'v3'
273
+ subject.revise
274
+ subject.name = 'Foo'
275
+ end
276
+
277
+ describe 'when latest version' do
278
+ it 'returns the version from db' do
279
+ subject.version(3)._version.must_equal 3
280
+ end
281
+ end
282
+
283
+ describe 'when previous version' do
284
+ it 'returns the version from db' do
285
+ subject.version(1)._version.must_equal 1
286
+ end
287
+ end
288
+
289
+ describe 'when version does not exist' do
290
+ it 'returns nil' do
291
+ subject.version(10).must_be_nil
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end
297
+
298
+ end
299
+ end
@@ -0,0 +1,45 @@
1
+ require 'bundler/setup'
2
+ require 'database_cleaner'
3
+ require 'minitest'
4
+ require 'minitest/autorun'
5
+ require 'minitest/spec'
6
+ require 'mongoid'
7
+
8
+ require 'mongoid_versioning'
9
+
10
+ # ---------------------------------------------------------------------
11
+
12
+ if ENV["CI"]
13
+ require "coveralls"
14
+ Coveralls.wear!
15
+ end
16
+
17
+ ENV["MONGOID_TEST_HOST"] ||= "localhost"
18
+ ENV["MONGOID_TEST_PORT"] ||= "27017"
19
+
20
+ HOST = ENV["MONGOID_TEST_HOST"]
21
+ PORT = ENV["MONGOID_TEST_PORT"].to_i
22
+
23
+ def database_id
24
+ "mongoid_versioning_test"
25
+ end
26
+
27
+ CONFIG = {
28
+ sessions: {
29
+ default: {
30
+ database: database_id,
31
+ hosts: [ "#{HOST}:#{PORT}" ]
32
+ }
33
+ }
34
+ }
35
+
36
+ Mongoid.configure do |config|
37
+ config.load_configuration(CONFIG)
38
+ end
39
+
40
+ DatabaseCleaner.orm = :mongoid
41
+ DatabaseCleaner.strategy = :truncation
42
+
43
+ class MiniTest::Spec
44
+ before(:each) { DatabaseCleaner.clean }
45
+ end
metadata ADDED
@@ -0,0 +1,172 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid_versioning
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tomas Celizna
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mongoid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: coveralls
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: database_cleaner
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Versioning Mongoid documents by means of separate collection.
126
+ email:
127
+ - tomas.celizna@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".travis.yml"
134
+ - Gemfile
135
+ - Gemfile.lock
136
+ - Guardfile
137
+ - LICENSE
138
+ - README.md
139
+ - Rakefile
140
+ - lib/mongoid_versioning.rb
141
+ - lib/mongoid_versioning/version.rb
142
+ - lib/mongoid_versioning/versioned.rb
143
+ - mongoid_versioning.gemspec
144
+ - test/mongoid_versioning/versioned_test.rb
145
+ - test/test_helper.rb
146
+ homepage: https://github.com/tomasc/mongoid_versioning
147
+ licenses:
148
+ - MIT
149
+ metadata: {}
150
+ post_install_message:
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ requirements: []
165
+ rubyforge_project:
166
+ rubygems_version: 2.2.2
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: Versioning Mongoid documents by means of separate collection.
170
+ test_files:
171
+ - test/mongoid_versioning/versioned_test.rb
172
+ - test/test_helper.rb