vestal_versions 1.0.2 → 2.0.0

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.
Files changed (69) hide show
  1. data/.gitignore +19 -20
  2. data/.travis.yml +22 -0
  3. data/CHANGELOG.md +7 -0
  4. data/Gemfile +10 -0
  5. data/README.rdoc +63 -36
  6. data/Rakefile +4 -43
  7. data/gemfiles/activerecord_3_0.gemfile +10 -0
  8. data/gemfiles/activerecord_3_1.gemfile +10 -0
  9. data/gemfiles/activerecord_3_2.gemfile +10 -0
  10. data/gemfiles/activerecord_4_0.gemfile +10 -0
  11. data/lib/generators/vestal_versions.rb +11 -0
  12. data/lib/generators/vestal_versions/migration/migration_generator.rb +17 -0
  13. data/{generators/vestal_versions → lib/generators/vestal_versions/migration}/templates/initializer.rb +0 -0
  14. data/{generators/vestal_versions → lib/generators/vestal_versions/migration}/templates/migration.rb +4 -3
  15. data/lib/vestal_versions.rb +39 -12
  16. data/lib/vestal_versions/changes.rb +43 -47
  17. data/lib/vestal_versions/conditions.rb +31 -43
  18. data/lib/vestal_versions/control.rb +162 -138
  19. data/lib/vestal_versions/creation.rb +67 -59
  20. data/lib/vestal_versions/deletion.rb +37 -0
  21. data/lib/vestal_versions/options.rb +6 -10
  22. data/lib/vestal_versions/reload.rb +7 -14
  23. data/lib/vestal_versions/reset.rb +15 -19
  24. data/lib/vestal_versions/reversion.rb +64 -52
  25. data/lib/vestal_versions/users.rb +36 -39
  26. data/lib/vestal_versions/version.rb +57 -2
  27. data/lib/vestal_versions/version_tagging.rb +51 -0
  28. data/lib/vestal_versions/versioned.rb +14 -17
  29. data/lib/vestal_versions/versions.rb +22 -7
  30. data/spec/spec_helper.rb +28 -0
  31. data/spec/support/models.rb +19 -0
  32. data/spec/support/schema.rb +25 -0
  33. data/spec/vestal_versions/changes_spec.rb +134 -0
  34. data/spec/vestal_versions/conditions_spec.rb +103 -0
  35. data/spec/vestal_versions/control_spec.rb +120 -0
  36. data/spec/vestal_versions/creation_spec.rb +90 -0
  37. data/spec/vestal_versions/deletion_spec.rb +86 -0
  38. data/spec/vestal_versions/options_spec.rb +45 -0
  39. data/spec/vestal_versions/reload_spec.rb +18 -0
  40. data/spec/vestal_versions/reset_spec.rb +111 -0
  41. data/spec/vestal_versions/reversion_spec.rb +103 -0
  42. data/spec/vestal_versions/users_spec.rb +21 -0
  43. data/spec/vestal_versions/version_spec.rb +61 -0
  44. data/spec/vestal_versions/version_tagging_spec.rb +39 -0
  45. data/spec/vestal_versions/versioned_spec.rb +16 -0
  46. data/spec/vestal_versions/versions_spec.rb +176 -0
  47. data/vestal_versions.gemspec +18 -100
  48. metadata +153 -102
  49. data/VERSION +0 -1
  50. data/generators/vestal_versions/vestal_versions_generator.rb +0 -10
  51. data/init.rb +0 -1
  52. data/lib/vestal_versions/configuration.rb +0 -40
  53. data/lib/vestal_versions/tagging.rb +0 -50
  54. data/test/changes_test.rb +0 -169
  55. data/test/conditions_test.rb +0 -137
  56. data/test/configuration_test.rb +0 -39
  57. data/test/control_test.rb +0 -152
  58. data/test/creation_test.rb +0 -110
  59. data/test/options_test.rb +0 -52
  60. data/test/reload_test.rb +0 -19
  61. data/test/reset_test.rb +0 -112
  62. data/test/reversion_test.rb +0 -68
  63. data/test/schema.rb +0 -43
  64. data/test/tagging_test.rb +0 -39
  65. data/test/test_helper.rb +0 -11
  66. data/test/users_test.rb +0 -25
  67. data/test/version_test.rb +0 -43
  68. data/test/versioned_test.rb +0 -18
  69. data/test/versions_test.rb +0 -172
@@ -2,63 +2,59 @@ module VestalVersions
2
2
  # Provides the ability to manipulate hashes in the specific format that ActiveRecord gives to
3
3
  # dirty attribute changes: string keys and unique, two-element array values.
4
4
  module Changes
5
- def self.included(base) # :nodoc:
6
- Hash.send(:include, HashMethods)
5
+ extend ActiveSupport::Concern
6
+ included do
7
+ Hash.class_eval{ include HashMethods }
7
8
 
8
- base.class_eval do
9
- include InstanceMethods
10
-
11
- after_update :merge_version_changes
12
- end
9
+ after_update :merge_version_changes
13
10
  end
14
11
 
15
12
  # Methods available to versioned ActiveRecord::Base instances in order to manage changes used
16
13
  # for version creation.
17
- module InstanceMethods
18
- # Collects an array of changes from a record's versions between the given range and compiles
19
- # them into one summary hash of changes. The +from+ and +to+ arguments can each be either a
20
- # version number, a symbol representing an association proxy method, a string representing a
21
- # version tag or a version object itself.
22
- def changes_between(from, to)
23
- from_number, to_number = versions.number_at(from), versions.number_at(to)
24
- return {} if from_number == to_number
25
- chain = versions.between(from_number, to_number).reject(&:initial?)
26
- return {} if chain.empty?
27
14
 
28
- backward = from_number > to_number
29
- backward ? chain.pop : chain.shift unless from_number == 1 || to_number == 1
15
+ # Collects an array of changes from a record's versions between the given range and compiles
16
+ # them into one summary hash of changes. The +from+ and +to+ arguments can each be either a
17
+ # version number, a symbol representing an association proxy method, a string representing a
18
+ # version tag or a version object itself.
19
+ def changes_between(from, to)
20
+ from_number, to_number = versions.number_at(from), versions.number_at(to)
21
+ return {} if from_number == to_number
22
+ chain = versions.between(from_number, to_number).reject(&:initial?)
23
+ return {} if chain.empty?
30
24
 
31
- chain.inject({}) do |changes, version|
32
- changes.append_changes!(backward ? version.changes.reverse_changes : version.changes)
33
- end
34
- end
25
+ backward = from_number > to_number
26
+ backward ? chain.pop : chain.shift unless from_number == 1 || to_number == 1
35
27
 
36
- private
37
- # Before a new version is created, the newly-changed attributes are appended onto a hash
38
- # of previously-changed attributes. Typically the previous changes will be empty, except in
39
- # the case that a control block is used where versions are to be merged. See
40
- # VestalVersions::Control for more information.
41
- def merge_version_changes
42
- version_changes.append_changes!(incremental_version_changes)
43
- end
28
+ chain.inject({}) do |changes, version|
29
+ changes.append_changes!(backward ? version.changes.reverse_changes : version.changes)
30
+ end
31
+ end
44
32
 
45
- # Stores the cumulative changes that are eventually used for version creation.
46
- def version_changes
47
- @version_changes ||= {}
48
- end
33
+ private
34
+ # Before a new version is created, the newly-changed attributes are appended onto a hash
35
+ # of previously-changed attributes. Typically the previous changes will be empty, except in
36
+ # the case that a control block is used where versions are to be merged. See
37
+ # VestalVersions::Control for more information.
38
+ def merge_version_changes
39
+ version_changes.append_changes!(incremental_version_changes)
40
+ end
49
41
 
50
- # Stores the incremental changes that are appended to the cumulative changes before version
51
- # creation. Incremental changes are reset when the record is saved because they represent
52
- # a subset of the dirty attribute changes, which are reset upon save.
53
- def incremental_version_changes
54
- changes.slice(*versioned_columns)
55
- end
42
+ # Stores the cumulative changes that are eventually used for version creation.
43
+ def version_changes
44
+ @version_changes ||= {}
45
+ end
56
46
 
57
- # Simply resets the cumulative changes after version creation.
58
- def reset_version_changes
59
- @version_changes = nil
60
- end
61
- end
47
+ # Stores the incremental changes that are appended to the cumulative changes before version
48
+ # creation. Incremental changes are reset when the record is saved because they represent
49
+ # a subset of the dirty attribute changes, which are reset upon save.
50
+ def incremental_version_changes
51
+ changes.slice(*versioned_columns)
52
+ end
53
+
54
+ # Simply resets the cumulative changes after version creation.
55
+ def reset_version_changes
56
+ @version_changes = nil
57
+ end
62
58
 
63
59
  # Instance methods included into Hash for dealing with manipulation of hashes in the specific
64
60
  # format of ActiveRecord::Base#changes.
@@ -122,4 +118,4 @@ module VestalVersions
122
118
  end
123
119
  end
124
120
  end
125
- end
121
+ end
@@ -2,19 +2,7 @@ module VestalVersions
2
2
  # Allows version creation to occur conditionally based on given <tt>:if</tt> and/or
3
3
  # <tt>:unless</tt> options.
4
4
  module Conditions
5
- def self.included(base) # :nodoc:
6
- base.class_eval do
7
- extend ClassMethods
8
- include InstanceMethods
9
-
10
- alias_method_chain :create_version?, :conditions
11
- alias_method_chain :update_version?, :conditions
12
-
13
- class << self
14
- alias_method_chain :prepare_versioned_options, :conditions
15
- end
16
- end
17
- end
5
+ extend ActiveSupport::Concern
18
6
 
19
7
  # Class methods on ActiveRecord::Base to prepare the <tt>:if</tt> and <tt>:unless</tt> options.
20
8
  module ClassMethods
@@ -25,11 +13,11 @@ module VestalVersions
25
13
  #
26
14
  # If all of the <tt>:if</tt> conditions are met and none of the <tt>:unless</tt> conditions
27
15
  # are unmet, than version creation will proceed, assuming all other conditions are also met.
28
- def prepare_versioned_options_with_conditions(options)
29
- result = prepare_versioned_options_without_conditions(options)
16
+ def prepare_versioned_options(options)
17
+ result = super(options)
30
18
 
31
- self.vestal_versions_options[:if] = Array(options.delete(:if)).map(&:to_proc)
32
- self.vestal_versions_options[:unless] = Array(options.delete(:unless)).map(&:to_proc)
19
+ vestal_versions_options[:if] = Array(options.delete(:if)).map(&:to_proc)
20
+ vestal_versions_options[:unless] = Array(options.delete(:unless)).map(&:to_proc)
33
21
 
34
22
  result
35
23
  end
@@ -37,33 +25,33 @@ module VestalVersions
37
25
 
38
26
  # Instance methods that determine based on the <tt>:if</tt> and <tt>:unless</tt> conditions,
39
27
  # whether a version is to be create or updated.
40
- module InstanceMethods
41
- private
42
- # After first determining whether the <tt>:if</tt> and <tt>:unless</tt> conditions are
43
- # satisfied, the original, unaliased +create_version?+ method is called to determine
44
- # whether a new version should be created upon update of the ActiveRecord::Base instance.
45
- def create_version_with_conditions?
46
- version_conditions_met? && create_version_without_conditions?
47
- end
28
+
29
+
30
+ private
31
+ # After first determining whether the <tt>:if</tt> and <tt>:unless</tt> conditions are
32
+ # satisfied, the original, unaliased +create_version?+ method is called to determine
33
+ # whether a new version should be created upon update of the ActiveRecord::Base instance.
34
+ def create_version?
35
+ version_conditions_met? && super
36
+ end
48
37
 
49
- # After first determining whether the <tt>:if</tt> and <tt>:unless</tt> conditions are
50
- # satisfied, the original, unaliased +update_version?+ method is called to determine
51
- # whther the last version should be updated to include changes merged from the current
52
- # ActiveRecord::Base instance update.
53
- #
54
- # The overridden +update_version?+ method simply returns false, effectively delegating
55
- # the decision to whether the <tt>:if</tt> and <tt>:unless</tt> conditions are met.
56
- def update_version_with_conditions?
57
- version_conditions_met? && update_version_without_conditions?
58
- end
38
+ # After first determining whether the <tt>:if</tt> and <tt>:unless</tt> conditions are
39
+ # satisfied, the original, unaliased +update_version?+ method is called to determine
40
+ # whther the last version should be updated to include changes merged from the current
41
+ # ActiveRecord::Base instance update.
42
+ #
43
+ # The overridden +update_version?+ method simply returns false, effectively delegating
44
+ # the decision to whether the <tt>:if</tt> and <tt>:unless</tt> conditions are met.
45
+ def update_version?
46
+ version_conditions_met? && super
47
+ end
59
48
 
60
- # Simply checks whether the <tt>:if</tt> and <tt>:unless</tt> conditions given in the
61
- # +versioned+ options are met: meaning that all procs in the <tt>:if</tt> array must
62
- # evaluate to a non-false, non-nil value and that all procs in the <tt>:unless</tt> array
63
- # must all evaluate to either false or nil.
64
- def version_conditions_met?
65
- vestal_versions_options[:if].all?{|p| p.call(self) } && !vestal_versions_options[:unless].any?{|p| p.call(self) }
66
- end
67
- end
49
+ # Simply checks whether the <tt>:if</tt> and <tt>:unless</tt> conditions given in the
50
+ # +versioned+ options are met: meaning that all procs in the <tt>:if</tt> array must
51
+ # evaluate to a non-false, non-nil value and that all procs in the <tt>:unless</tt> array
52
+ # must all evaluate to either false or nil.
53
+ def version_conditions_met?
54
+ vestal_versions_options[:if].all?{|p| p.call(self) } && !vestal_versions_options[:unless].any?{|p| p.call(self) }
55
+ end
68
56
  end
69
57
  end
@@ -2,174 +2,198 @@ module VestalVersions
2
2
  # The control feature allows use of several code blocks that provide finer control over whether
3
3
  # a new version is created, or a previous version is updated.
4
4
  module Control
5
- def self.included(base) # :nodoc:
6
- base.class_eval do
7
- include InstanceMethods
5
+ extend ActiveSupport::Concern
8
6
 
9
- alias_method_chain :create_version?, :control
10
- alias_method_chain :update_version?, :control
11
- end
7
+ included do
8
+ class_attribute :_skip_version, :instance_writer => false
12
9
  end
13
10
 
11
+
14
12
  # Control blocks are called on ActiveRecord::Base instances as to not cause any conflict with
15
13
  # other instances of the versioned class whose behavior could be inadvertently altered within
16
14
  # a control block.
17
- module InstanceMethods
18
- # The +skip_version+ block simply allows for updates to be made to an instance of a versioned
19
- # ActiveRecord model while ignoring all new version creation. The <tt>:if</tt> and
20
- # <tt>:unless</tt> conditions (if given) will not be evaulated inside a +skip_version+ block.
21
- #
22
- # When the block closes, the instance is automatically saved, so explicitly saving the
23
- # object within the block is unnecessary.
24
- #
25
- # == Example
26
- #
27
- # user = User.find_by_first_name("Steve")
28
- # user.version # => 1
29
- # user.skip_version do
30
- # user.first_name = "Stephen"
31
- # end
32
- # user.version # => 1
33
- def skip_version
34
- with_version_flag(:skip_version) do
35
- yield if block_given?
36
- save
37
- end
15
+
16
+ # The +skip_version+ block simply allows for updates to be made to an instance of a versioned
17
+ # ActiveRecord model while ignoring all new version creation. The <tt>:if</tt> and
18
+ # <tt>:unless</tt> conditions (if given) will not be evaulated inside a +skip_version+ block.
19
+ #
20
+ # When the block closes, the instance is automatically saved, so explicitly saving the
21
+ # object within the block is unnecessary.
22
+ #
23
+ # == Example
24
+ #
25
+ # user = User.find_by_first_name("Steve")
26
+ # user.version # => 1
27
+ # user.skip_version do
28
+ # user.first_name = "Stephen"
29
+ # end
30
+ # user.version # => 1
31
+ def skip_version
32
+ _with_version_flag(:_skip_version) do
33
+ yield if block_given?
34
+ save
38
35
  end
36
+ end
39
37
 
40
- # Behaving almost identically to the +skip_version+ block, the only difference with the
41
- # +skip_version!+ block is that the save automatically performed at the close of the block
42
- # is a +save!+, meaning that an exception will be raised if the object cannot be saved.
43
- def skip_version!
44
- with_version_flag(:skip_version) do
45
- yield if block_given?
46
- save!
47
- end
38
+ # Behaving almost identically to the +skip_version+ block, the only difference with the
39
+ # +skip_version!+ block is that the save automatically performed at the close of the block
40
+ # is a +save!+, meaning that an exception will be raised if the object cannot be saved.
41
+ def skip_version!
42
+ _with_version_flag(:_skip_version) do
43
+ yield if block_given?
44
+ save!
48
45
  end
46
+ end
49
47
 
50
- # A convenience method for determining whether a versioned instance is set to skip its next
51
- # version creation.
52
- def skip_version?
53
- !!@skip_version
48
+ # Merging versions with the +merge_version+ block will take all of the versions that would
49
+ # be created within the block and merge them into one version and pushing that single version
50
+ # onto the ActiveRecord::Base instance's version history. A new version will be created and
51
+ # the instance's version number will be incremented.
52
+ #
53
+ # == Example
54
+ #
55
+ # user = User.find_by_first_name("Steve")
56
+ # user.version # => 1
57
+ # user.merge_version do
58
+ # user.update_attributes(:first_name => "Steven", :last_name => "Tyler")
59
+ # user.update_attribute(:first_name, "Stephen")
60
+ # user.update_attribute(:last_name, "Richert")
61
+ # end
62
+ # user.version # => 2
63
+ # user.versions.last.changes
64
+ # # => {"first_name" => ["Steve", "Stephen"], "last_name" => ["Jobs", "Richert"]}
65
+ #
66
+ # See VestalVersions::Changes for an explanation on how changes are appended.
67
+ def merge_version
68
+ _with_version_flag(:merge_version) do
69
+ yield if block_given?
54
70
  end
71
+ save
72
+ end
55
73
 
56
- # Merging versions with the +merge_version+ block will take all of the versions that would
57
- # be created within the block and merge them into one version and pushing that single version
58
- # onto the ActiveRecord::Base instance's version history. A new version will be created and
59
- # the instance's version number will be incremented.
60
- #
61
- # == Example
62
- #
63
- # user = User.find_by_first_name("Steve")
64
- # user.version # => 1
65
- # user.merge_version do
66
- # user.update_attributes(:first_name => "Steven", :last_name => "Tyler")
67
- # user.update_attribute(:first_name, "Stephen")
68
- # user.update_attribute(:last_name, "Richert")
69
- # end
70
- # user.version # => 2
71
- # user.versions.last.changes
72
- # # => {"first_name" => ["Steve", "Stephen"], "last_name" => ["Jobs", "Richert"]}
73
- #
74
- # See VestalVersions::Changes for an explanation on how changes are appended.
75
- def merge_version
76
- with_version_flag(:merge_version) do
77
- yield if block_given?
78
- end
74
+ # Behaving almost identically to the +merge_version+ block, the only difference with the
75
+ # +merge_version!+ block is that the save automatically performed at the close of the block
76
+ # is a +save!+, meaning that an exception will be raised if the object cannot be saved.
77
+ def merge_version!
78
+ _with_version_flag(:merge_version) do
79
+ yield if block_given?
80
+ end
81
+ save!
82
+ end
83
+
84
+ # A convenience method for determining whether a versioned instance is set to merge its next
85
+ # versions into one before version creation.
86
+ def merge_version?
87
+ !!@merge_version
88
+ end
89
+
90
+ # Appending versions with the +append_version+ block acts similarly to the +merge_version+
91
+ # block in that all would-be version creations within the block are defered until the block
92
+ # closes. The major difference is that with +append_version+, a new version is not created.
93
+ # Rather, the cumulative changes are appended to the serialized changes of the instance's
94
+ # last version. A new version is not created, so the version number is not incremented.
95
+ #
96
+ # == Example
97
+ #
98
+ # user = User.find_by_first_name("Steve")
99
+ # user.version # => 2
100
+ # user.versions.last.changes
101
+ # # => {"first_name" => ["Stephen", "Steve"]}
102
+ # user.append_version do
103
+ # user.last_name = "Jobs"
104
+ # end
105
+ # user.versions.last.changes
106
+ # # => {"first_name" => ["Stephen", "Steve"], "last_name" => ["Richert", "Jobs"]}
107
+ # user.version # => 2
108
+ #
109
+ # See VestalVersions::Changes for an explanation on how changes are appended.
110
+ def append_version
111
+ _with_version_flag(:merge_version) do
112
+ yield if block_given?
113
+ end
114
+
115
+ _with_version_flag(:append_version) do
79
116
  save
80
117
  end
118
+ end
81
119
 
82
- # Behaving almost identically to the +merge_version+ block, the only difference with the
83
- # +merge_version!+ block is that the save automatically performed at the close of the block
84
- # is a +save!+, meaning that an exception will be raised if the object cannot be saved.
85
- def merge_version!
86
- with_version_flag(:merge_version) do
87
- yield if block_given?
88
- end
89
- save!
120
+ # Behaving almost identically to the +append_version+ block, the only difference with the
121
+ # +append_version!+ block is that the save automatically performed at the close of the block
122
+ # is a +save!+, meaning that an exception will be raised if the object cannot be saved.
123
+ def append_version!
124
+ _with_version_flag(:merge_version) do
125
+ yield if block_given?
90
126
  end
91
127
 
92
- # A convenience method for determining whether a versioned instance is set to merge its next
93
- # versions into one before version creation.
94
- def merge_version?
95
- !!@merge_version
128
+ _with_version_flag(:append_version) do
129
+ save!
96
130
  end
131
+ end
132
+
133
+ # A convenience method for determining whether a versioned instance is set to append its next
134
+ # version's changes into the last version changes.
135
+ def append_version?
136
+ !!@append_version
137
+ end
97
138
 
98
- # Appending versions with the +append_version+ block acts similarly to the +merge_version+
99
- # block in that all would-be version creations within the block are defered until the block
100
- # closes. The major difference is that with +append_version+, a new version is not created.
101
- # Rather, the cumulative changes are appended to the serialized changes of the instance's
102
- # last version. A new version is not created, so the version number is not incremented.
139
+ # Used for each control block, the +_with_version_flag+ method sets a given variable to
140
+ # true and then executes the given block, ensuring that the variable is returned to a nil
141
+ # value before returning. This is useful to be certain that one of the control flag
142
+ # instance variables isn't inadvertently left in the "on" position by execution within the
143
+ # block raising an exception.
144
+ def _with_version_flag(flag)
145
+ instance_variable_set("@#{flag}", true)
146
+ yield
147
+ ensure
148
+ remove_instance_variable("@#{flag}")
149
+ end
150
+
151
+ # Overrides the basal +create_version?+ method to make sure that new versions are not
152
+ # created when inside any of the control blocks (until the block terminates).
153
+ def create_version?
154
+ !_skip_version? && !merge_version? && !append_version? && super
155
+ end
156
+
157
+ # Overrides the basal +update_version?+ method to allow the last version of an versioned
158
+ # ActiveRecord::Base instance to be updated at the end of an +append_version+ block.
159
+ def update_version?
160
+ append_version?
161
+ end
162
+
163
+ module ClassMethods
164
+ # The +skip_version+ block simply allows for updates to be made to an instance of a versioned
165
+ # ActiveRecord model while ignoring all new version creation. The <tt>:if</tt> and
166
+ # <tt>:unless</tt> conditions (if given) will not be evaulated inside a +skip_version+ block.
167
+ #
168
+ # When the block closes, the instance is automatically saved, so explicitly saving the
169
+ # object within the block is unnecessary.
103
170
  #
104
171
  # == Example
105
172
  #
106
173
  # user = User.find_by_first_name("Steve")
107
- # user.version # => 2
108
- # user.versions.last.changes
109
- # # => {"first_name" => ["Stephen", "Steve"]}
110
- # user.append_version do
111
- # user.last_name = "Jobs"
174
+ # user.version # => 1
175
+ # user.skip_version do
176
+ # user.first_name = "Stephen"
112
177
  # end
113
- # user.versions.last.changes
114
- # # => {"first_name" => ["Stephen", "Steve"], "last_name" => ["Richert", "Jobs"]}
115
- # user.version # => 2
116
- #
117
- # See VestalVersions::Changes for an explanation on how changes are appended.
118
- def append_version
119
- with_version_flag(:merge_version) do
120
- yield if block_given?
121
- end
122
-
123
- with_version_flag(:append_version) do
124
- save
125
- end
126
- end
127
-
128
- # Behaving almost identically to the +append_version+ block, the only difference with the
129
- # +append_version!+ block is that the save automatically performed at the close of the block
130
- # is a +save!+, meaning that an exception will be raised if the object cannot be saved.
131
- def append_version!
132
- with_version_flag(:merge_version) do
178
+ # user.version # => 1
179
+ def skip_version
180
+ _with_version_flag(:_skip_version) do
133
181
  yield if block_given?
134
182
  end
135
-
136
- with_version_flag(:append_version) do
137
- save!
138
- end
139
183
  end
140
184
 
141
- # A convenience method for determining whether a versioned instance is set to append its next
142
- # version's changes into the last version changes.
143
- def append_version?
144
- !!@append_version
185
+ # Used for each control block, the +with_version_flag+ method sets a given variable to
186
+ # true and then executes the given block, ensuring that the variable is returned to a nil
187
+ # value before returning. This is useful to be certain that one of the control flag
188
+ # instance variables isn't inadvertently left in the "on" position by execution within the
189
+ # block raising an exception.
190
+ def _with_version_flag(flag)
191
+ self.send("#{flag}=", true)
192
+ yield
193
+ ensure
194
+ self.send("#{flag}=", nil)
145
195
  end
146
196
 
147
- private
148
- # Used for each control block, the +with_version_flag+ method sets a given variable to
149
- # true and then executes the given block, ensuring that the variable is returned to a nil
150
- # value before returning. This is useful to be certain that one of the control flag
151
- # instance variables isn't inadvertently left in the "on" position by execution within the
152
- # block raising an exception.
153
- def with_version_flag(flag)
154
- begin
155
- instance_variable_set("@#{flag}", true)
156
- yield
157
- ensure
158
- instance_variable_set("@#{flag}", nil)
159
- end
160
- end
161
-
162
- # Overrides the basal +create_version?+ method to make sure that new versions are not
163
- # created when inside any of the control blocks (until the block terminates).
164
- def create_version_with_control?
165
- !skip_version? && !merge_version? && !append_version? && create_version_without_control?
166
- end
167
-
168
- # Overrides the basal +update_version?+ method to allow the last version of an versioned
169
- # ActiveRecord::Base instance to be updated at the end of an +append_version+ block.
170
- def update_version_with_control?
171
- append_version?
172
- end
173
197
  end
174
198
  end
175
199
  end