vidibus-versioning 0.3.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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 "vidibus-versioning"` to your Gemfile. Then call `bundle install` on your console.
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
- To apply versioning to your model is easy. An example:
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, :type => String
24
- field :text, :type => String
23
+ field :title, type: String
24
+ field :text, type: String
25
25
 
26
- versioned :title, :text, :editing_time => 300 # this is optional
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 `Article.unversioned_attributes`, which are `_id`, `_type`, `uuid`,
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 :editing_time => 300` you set a
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 - an article in this case - are:
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, :title => "Wicked!") # returns version 3 with a new title applied
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(:title => "Old shit")
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 = "New shit" # set the new 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-2013 Andre Pankratz. See LICENSE for details.
123
+ Copyright (c) 2011-2015 Andre Pankratz. See LICENSE for details.
@@ -1,5 +1,5 @@
1
1
  module Vidibus
2
2
  module Versioning
3
- VERSION = '0.3.0'
3
+ VERSION = '0.3.3'
4
4
  end
5
5
  end
@@ -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
- before_update :reset_version_cache
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
- self.class.find(_id).tap do |copy|
56
- copy.apply_version!(*args)
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
- return false if invalid?
114
- saved = persist_version
115
- (saved == nil) ? super(*args) : saved
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 and version_obj.new_record?
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
- return unless versioned_attributes_changed?
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
- return saved unless version_cache.self_version
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.0
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: 2013-10-15 00:00:00.000000000 Z
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: 2214928841731694107
188
+ hash: -472131419390018978
189
189
  required_rubygems_version: !ruby/object:Gem::Requirement
190
190
  none: false
191
191
  requirements: