vidibus-versioning 0.3.0 → 0.3.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 +12 -12
- data/lib/vidibus/versioning/_version.rb +1 -1
- data/lib/vidibus/versioning/mongoid.rb +76 -15
- data/lib/vidibus/versioning/version.rb +2 -2
- metadata +3 -3
data/README.md
CHANGED
@@ -7,12 +7,12 @@ This gem is part of [Vidibus](http://vidibus.org), an open source toolset for bu
|
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
10
|
-
Add `gem
|
10
|
+
Add `gem 'vidibus-versioning'` to your Gemfile. Then call `bundle install` on your console.
|
11
11
|
|
12
12
|
|
13
13
|
## Usage
|
14
14
|
|
15
|
-
|
15
|
+
Applying versioning to your model is easy. An example:
|
16
16
|
|
17
17
|
```ruby
|
18
18
|
class Article
|
@@ -20,17 +20,17 @@ class Article
|
|
20
20
|
include Vidibus::Uuid::Mongoid
|
21
21
|
include Vidibus::Versioning::Mongoid # this is mandatory
|
22
22
|
|
23
|
-
field :title, :
|
24
|
-
field :text, :
|
23
|
+
field :title, type: String
|
24
|
+
field :text, type: String
|
25
25
|
|
26
|
-
versioned :title, :text, :
|
26
|
+
versioned :title, :text, editing_time: 300 # this is optional
|
27
27
|
end
|
28
28
|
```
|
29
29
|
|
30
30
|
### Versioned attributes
|
31
31
|
|
32
32
|
Including the versioning engine by adding `include Vidibus::Versioning::Mongoid` will set all fields of your model as
|
33
|
-
versioned ones, except those contained in
|
33
|
+
versioned ones, except those contained in `<Class>.unversioned_attributes`, which are `_id`, `_type`, `uuid`,
|
34
34
|
`updated_at`, `created_at`, and `version_number`.
|
35
35
|
|
36
36
|
An optional `versioned` call lets you specify the versioned attributes precisely by providing a list. For example, to
|
@@ -39,14 +39,14 @@ set the title as only attribute to be versioned, call `versioned :title`.
|
|
39
39
|
|
40
40
|
### Combined versioning
|
41
41
|
|
42
|
-
`versioned` also takes options to tweak versioning behaviour. By calling `versioned :
|
42
|
+
`versioned` also takes options to tweak versioning behaviour. By calling `versioned editing_time: 300` you set a
|
43
43
|
timespan for the version to accept changes so all changes within 300 seconds will be treated as one version.
|
44
44
|
That behaviour is especially useful if your model's UI allows changing attributes separately, like in-place editing.
|
45
45
|
|
46
46
|
|
47
47
|
### Migrating
|
48
48
|
|
49
|
-
The basic methods for migrating a versioned object
|
49
|
+
The basic methods for migrating a versioned object – an article in this case – are:
|
50
50
|
|
51
51
|
```ruby
|
52
52
|
article.migrate!(32) # migrates to version 32
|
@@ -83,7 +83,7 @@ article.version?(3) # returns false if version 3 does not exist
|
|
83
83
|
It is even possible to apply versioned attributes directly by adding them to the `version` call:
|
84
84
|
|
85
85
|
```ruby
|
86
|
-
article.version(3, :
|
86
|
+
article.version(3, title: 'Wicked!') # returns version 3 with a new title applied
|
87
87
|
```
|
88
88
|
|
89
89
|
You may treat the article object with an applied version like the article itself. All changes will
|
@@ -93,10 +93,10 @@ that can be scheduled by [Vidibus::VersionScheduler](https://github.com/vidibus/
|
|
93
93
|
A workflow example:
|
94
94
|
|
95
95
|
```ruby
|
96
|
-
article = Article.create(:
|
96
|
+
article = Article.create(title: 'Old stuff')
|
97
97
|
future_article = article.version(:new) # initialize a new version
|
98
98
|
future_article.updated_at = 1.day.since # set a date in the future
|
99
|
-
future_article.title =
|
99
|
+
future_article.title = 'New stuff' # set the new title
|
100
100
|
future_article.save # save the version
|
101
101
|
```
|
102
102
|
|
@@ -120,4 +120,4 @@ article.version_object # => nil
|
|
120
120
|
|
121
121
|
## Copyright
|
122
122
|
|
123
|
-
Copyright (c) 2011-
|
123
|
+
Copyright (c) 2011-2015 Andre Pankratz. See LICENSE for details.
|
@@ -14,13 +14,15 @@ module Vidibus
|
|
14
14
|
|
15
15
|
after_initialize :original_attributes
|
16
16
|
after_initialize :set_version_updated_at, :unless => :version_updated_at
|
17
|
-
|
17
|
+
before_save :reset_version_cache
|
18
18
|
|
19
19
|
mattr_accessor :versioned_attributes, :unversioned_attributes, :versioning_options
|
20
20
|
self.versioned_attributes = []
|
21
21
|
self.unversioned_attributes = %w[_id _type uuid updated_at created_at version_number version_updated_at]
|
22
22
|
self.versioning_options = {}
|
23
23
|
|
24
|
+
define_model_callbacks :version_save
|
25
|
+
|
24
26
|
# Returns the attributes that should be versioned.
|
25
27
|
# If no versioned attributes have been defined on class level,
|
26
28
|
# all attributes will be returned except the unversioned ones.
|
@@ -52,8 +54,10 @@ module Vidibus
|
|
52
54
|
# 48 returns version 48 of self
|
53
55
|
#
|
54
56
|
def version(*args)
|
55
|
-
|
56
|
-
|
57
|
+
::Mongoid.unit_of_work(disable: :current) do
|
58
|
+
self.class.find(_id).tap do |copy|
|
59
|
+
copy.apply_version!(*args)
|
60
|
+
end
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
@@ -76,6 +80,20 @@ module Vidibus
|
|
76
80
|
end
|
77
81
|
end
|
78
82
|
|
83
|
+
# Returns version at given time.
|
84
|
+
#
|
85
|
+
def version_at(input)
|
86
|
+
input = Time.parse(input) unless input.is_a?(Time)
|
87
|
+
match = versions.
|
88
|
+
where(:created_at.lte => input).
|
89
|
+
desc(:created_at).first
|
90
|
+
if match
|
91
|
+
version(match.number)
|
92
|
+
else
|
93
|
+
raise VersionNotFoundError.new("no version at #{input}")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
79
97
|
# Applies attributes of wanted version on self.
|
80
98
|
# Stores current attributes in a new version.
|
81
99
|
def migrate!(number = nil)
|
@@ -91,6 +109,10 @@ module Vidibus
|
|
91
109
|
|
92
110
|
set_original_version_obj
|
93
111
|
|
112
|
+
if version_object.future?
|
113
|
+
version_object.update_attributes(:created_at => Time.now)
|
114
|
+
end
|
115
|
+
|
94
116
|
self.attributes = version_attributes
|
95
117
|
self.version_number = version_cache.wanted_version_number
|
96
118
|
save!
|
@@ -110,9 +132,16 @@ module Vidibus
|
|
110
132
|
|
111
133
|
# Saves the record and handles version persistence.
|
112
134
|
def save(*args)
|
113
|
-
|
114
|
-
|
115
|
-
|
135
|
+
saved = false
|
136
|
+
if valid?
|
137
|
+
run_callbacks(:version_save) do
|
138
|
+
saved = persist_version
|
139
|
+
if saved == nil
|
140
|
+
saved = super(*args)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
saved
|
116
145
|
end
|
117
146
|
|
118
147
|
# Raises a validation error if saving fails.
|
@@ -144,7 +173,30 @@ module Vidibus
|
|
144
173
|
|
145
174
|
# Returns true if version requested is a new one.
|
146
175
|
def new_version?
|
147
|
-
version_obj
|
176
|
+
!!(version_obj && version_obj.new_record?)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Returns true if versioned attributes have changed.
|
180
|
+
def versioned_attributes_changed?
|
181
|
+
versioned_attributes != original_attributes
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns changes to unversioned attributes.
|
185
|
+
# "Unversioned attributes" are attributes that are not versioned and
|
186
|
+
# should be applied to all versions, but are not included in
|
187
|
+
# #unversioned_attributes either.
|
188
|
+
def unversioned_changes
|
189
|
+
changes.except(versioned_attributes.keys + unversioned_attributes)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns true if unversioned attributes have changed.
|
193
|
+
def unversioned_attributes_changed?
|
194
|
+
unversioned_changes.any?
|
195
|
+
end
|
196
|
+
|
197
|
+
# Returns version number of original (unversioned) instance.
|
198
|
+
def original_version_number
|
199
|
+
version_cache.original_version_number || version_number
|
148
200
|
end
|
149
201
|
|
150
202
|
protected
|
@@ -161,7 +213,7 @@ module Vidibus
|
|
161
213
|
unless version_obj
|
162
214
|
raise VersionNotFoundError.new("version #{version_cache.wanted_version_number} does not exist")
|
163
215
|
end
|
164
|
-
|
216
|
+
version_cache.original_version_number ||= version_number
|
165
217
|
self.attributes = version_attributes
|
166
218
|
self.version_number = version_cache.wanted_version_number
|
167
219
|
if time = version_obj.created_at
|
@@ -177,11 +229,6 @@ module Vidibus
|
|
177
229
|
@original_attributes ||= versioned_attributes
|
178
230
|
end
|
179
231
|
|
180
|
-
# Returns true if versioned attributes were changed.
|
181
|
-
def versioned_attributes_changed?
|
182
|
-
versioned_attributes != original_attributes
|
183
|
-
end
|
184
|
-
|
185
232
|
# Returns original attributes with attributes of version object and wanted attributes merged in.
|
186
233
|
# TODO: Only return attributes that are present on the object. They may have changed.
|
187
234
|
def version_attributes
|
@@ -287,6 +334,7 @@ module Vidibus
|
|
287
334
|
def version_cache
|
288
335
|
@version_cache ||= Struct.new(
|
289
336
|
:wanted_version_number,
|
337
|
+
:original_version_number,
|
290
338
|
:existing_version_wanted,
|
291
339
|
:wanted_attributes,
|
292
340
|
:new_version_number,
|
@@ -305,7 +353,14 @@ module Vidibus
|
|
305
353
|
#
|
306
354
|
def persist_version
|
307
355
|
return if new_record?
|
308
|
-
|
356
|
+
if !versioned_attributes_changed?
|
357
|
+
# Reset version number if new version won't be persisted.
|
358
|
+
if version_cache.new_version_number
|
359
|
+
self.version_number = version_number_was
|
360
|
+
end
|
361
|
+
return
|
362
|
+
end
|
363
|
+
|
309
364
|
if version_cache.original_version_obj
|
310
365
|
version_cache.original_version_obj.save!
|
311
366
|
elsif version_cache.wanted_version_number
|
@@ -315,7 +370,13 @@ module Vidibus
|
|
315
370
|
:created_at => updated_at
|
316
371
|
})
|
317
372
|
end
|
318
|
-
|
373
|
+
unless version_cache.self_version
|
374
|
+
if saved == false
|
375
|
+
return false
|
376
|
+
elsif !unversioned_attributes_changed?
|
377
|
+
return true
|
378
|
+
end
|
379
|
+
end
|
319
380
|
elsif version_obj
|
320
381
|
version_obj.update_attributes!({
|
321
382
|
:versioned_attributes => original_attributes
|
@@ -21,11 +21,11 @@ module Vidibus
|
|
21
21
|
scope :timeline, desc(:created_at)
|
22
22
|
|
23
23
|
def past?
|
24
|
-
created_at && created_at < Time.now
|
24
|
+
!!(created_at && created_at < Time.now)
|
25
25
|
end
|
26
26
|
|
27
27
|
def future?
|
28
|
-
created_at && created_at >= Time.now
|
28
|
+
!!(created_at && created_at >= Time.now)
|
29
29
|
end
|
30
30
|
|
31
31
|
protected
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vidibus-versioning
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-05-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongoid
|
@@ -185,7 +185,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
185
185
|
version: '0'
|
186
186
|
segments:
|
187
187
|
- 0
|
188
|
-
hash:
|
188
|
+
hash: -472131419390018978
|
189
189
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
190
190
|
none: false
|
191
191
|
requirements:
|