workflow 0.8.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ before_install:
2
+ - sudo apt-get install -qq graphviz
3
+
4
+ rvm:
5
+ - 1.9.3
6
+ - 2.0.0
7
+
8
+ matrix:
9
+ include:
10
+ # legacy build: Ruby 1.8.7, Rails 2.3, less features, smaller test set
11
+ - rvm: 1.8.7
12
+ gemfile: gemfiles/Gemfile.rails-2.3.x
13
+ # running a smaller test set for old Rails and Ruby
14
+ script: rake test_without_new_versions
data/README.markdown CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://travis-ci.org/geekq/workflow.png?branch=master)](https://travis-ci.org/geekq/workflow)
2
+
1
3
  What is workflow?
2
4
  -----------------
3
5
 
@@ -501,6 +503,24 @@ when using both a block and a callback method for an event, the block executes p
501
503
  Changelog
502
504
  ---------
503
505
 
506
+ ### New in the version 1.0.0
507
+
508
+ * **Support to private/protected callback methods.**
509
+ See also issues [#53](https://github.com/geekq/workflow/pull/53)
510
+ and [#58](https://github.com/geekq/workflow/pull/58). With the new
511
+ implementation:
512
+
513
+ * callback methods can be hidden (non public): both private methods
514
+ in the immediate class and protected methods somewhere in the class
515
+ hierarchy are supported
516
+ * no unintentional calls on `fail!` and other Kernel methods
517
+ * inheritance hierarchy with workflow is supported
518
+
519
+ * using Rails' 3.1 `update_column` whenever available so only the
520
+ workflow state column and not other pending attribute changes are
521
+ saved on state transition. Fallback to `update_attribute` for older
522
+ Rails and other ORMs. [commit](https://github.com/geekq/workflow/commit/7e091d8ded1aeeb0a86647bbf7d78ab3c9d0c458)
523
+
504
524
  ### New in the version 0.8.7
505
525
 
506
526
  * switch from [jeweler][] to pure bundler for building gems
data/Rakefile CHANGED
@@ -15,6 +15,15 @@ end
15
15
 
16
16
  require 'rake'
17
17
  Rake::TestTask.new do |t|
18
+ t.libs << 'test'
19
+ t.verbose = true
20
+ t.warning = true
21
+ t.test_files = FileList['test/*_test.rb'] + FileList['test/new_versions/*_test.rb']
22
+ end
23
+
24
+ Rake::TestTask.new do |t|
25
+ t.name = 'test_without_new_versions'
26
+ t.libs << 'test'
18
27
  t.verbose = true
19
28
  t.warning = true
20
29
  t.pattern = 'test/*_test.rb'
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem "rdoc", ">= 3.12"
5
+ gem "bundler", ">= 1.0.0"
6
+ gem "activerecord", "~>2.3.15"
7
+ gem "sqlite3"
8
+ gem "mocha"
9
+ gem "rake"
10
+ end
data/lib/workflow.rb CHANGED
@@ -284,9 +284,14 @@ module Workflow
284
284
  def run_action(action, *args)
285
285
  instance_exec(*args, &action) if action
286
286
  end
287
-
287
+
288
288
  def has_callback?(action)
289
- self.respond_to?(action) or self.class.private_method_defined?(action)
289
+ # 1. public callback method or
290
+ # 2. protected method somewhere in the class hierarchy or
291
+ # 3. private in the immediate class (parent classes ignored)
292
+ self.respond_to?(action) or
293
+ self.class.protected_method_defined?(action) or
294
+ self.private_methods(false).map(&:to_sym).include?(action)
290
295
  end
291
296
 
292
297
  def run_action_callback(action_name, *args)
@@ -338,7 +343,13 @@ module Workflow
338
343
  # On transition the new workflow state is immediately saved in the
339
344
  # database.
340
345
  def persist_workflow_state(new_value)
341
- update_attributes self.class.workflow_column => new_value
346
+ if self.respond_to? :update_column
347
+ # Rails 3.1 or newer
348
+ update_column self.class.workflow_column, new_value
349
+ else
350
+ # older Rails; beware of side effect: other (pending) attribute changes will be persisted too
351
+ update_attribute self.class.workflow_column, new_value
352
+ end
342
353
  end
343
354
 
344
355
  private
@@ -1,3 +1,3 @@
1
1
  module Workflow
2
- VERSION = "0.8.7"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,61 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+ require 'workflow'
3
+ class AdvanceExamplesTest < ActiveRecordTestCase
4
+
5
+ class Article
6
+ include Workflow
7
+ workflow do
8
+ state :new do
9
+ event :submit, :transitions_to => :awaiting_review
10
+ end
11
+ state :awaiting_review do
12
+ event :review, :transitions_to => :being_reviewed
13
+ end
14
+ state :being_reviewed do
15
+ event :accept, :transitions_to => :accepted
16
+ event :reject, :transitions_to => :rejected
17
+ end
18
+ state :accepted do
19
+ end
20
+ state :rejected do
21
+ end
22
+ end
23
+ end
24
+
25
+ test '#63 undoing event - automatically add revert events for every defined event' do
26
+ # also see https://github.com/geekq/workflow/issues/63
27
+ spec = Article.workflow_spec
28
+ spec.state_names.each do |state_name|
29
+ state = spec.states[state_name]
30
+
31
+ (state.events.values.reject {|e| e.name.to_s =~ /^revert_/ }).each do |event|
32
+ event_name = event.name
33
+ revert_event_name = "revert_" + event_name.to_s
34
+
35
+ # Add revert events
36
+ spec.states[event.transitions_to.to_sym].events[revert_event_name.to_sym] =
37
+ Workflow::Event.new(revert_event_name, state, {})
38
+
39
+ # Add methods for revert events
40
+ Article.module_eval do
41
+ define_method "#{revert_event_name}!".to_sym do |*args|
42
+ process_event!(revert_event_name, *args)
43
+ end
44
+ define_method "can_#{revert_event_name}?" do
45
+ return self.current_state.events.include?(revert_event_name)
46
+ end
47
+ end
48
+
49
+ end
50
+ end
51
+
52
+ a = Article.new
53
+ assert(a.new?, "should start with the 'new' state")
54
+ a.submit!
55
+ assert(a.awaiting_review?, "should now be in 'awaiting_review' state")
56
+ assert_equal(['revert_submit', 'review'], a.current_state.events.keys.map(&:to_s).sort)
57
+ a.revert_submit! # this method is added by our meta programming magic above
58
+ assert(a.new?, "should now be back in the 'new' state")
59
+ end
60
+
61
+ end
@@ -0,0 +1,104 @@
1
+ require 'test_helper'
2
+
3
+ $VERBOSE = false
4
+ require 'active_record'
5
+ require 'logger'
6
+ require 'sqlite3'
7
+ require 'workflow'
8
+ require 'mocha/setup'
9
+ require 'stringio'
10
+
11
+ ActiveRecord::Migration.verbose = false
12
+
13
+ class AttrProtectedTestOrder < ActiveRecord::Base
14
+ include Workflow
15
+
16
+ workflow do
17
+ state :submitted do
18
+ event :accept, :transitions_to => :accepted, :meta => {:doc_weight => 8} do |reviewer, args|
19
+ end
20
+ end
21
+ state :accepted do
22
+ event :ship, :transitions_to => :shipped
23
+ end
24
+ state :shipped
25
+ end
26
+
27
+ attr_accessible :title # protecting all the other attributes
28
+
29
+ end
30
+
31
+ AttrProtectedTestOrder.logger = Logger.new(STDOUT) # active_record 2.3 expects a logger instance
32
+ AttrProtectedTestOrder.logger.level = Logger::WARN # switch to Logger::DEBUG to see the SQL statements
33
+
34
+ class AttrProtectedTest < ActiveRecordTestCase
35
+
36
+ def setup
37
+ super
38
+
39
+ ActiveRecord::Schema.define do
40
+ create_table :attr_protected_test_orders do |t|
41
+ t.string :title, :null => false
42
+ t.string :workflow_state
43
+ end
44
+ end
45
+
46
+ exec "INSERT INTO attr_protected_test_orders(title, workflow_state) VALUES('order1', 'submitted')"
47
+ exec "INSERT INTO attr_protected_test_orders(title, workflow_state) VALUES('order2', 'accepted')"
48
+ exec "INSERT INTO attr_protected_test_orders(title, workflow_state) VALUES('order3', 'accepted')"
49
+ exec "INSERT INTO attr_protected_test_orders(title, workflow_state) VALUES('order4', 'accepted')"
50
+ exec "INSERT INTO attr_protected_test_orders(title, workflow_state) VALUES('order5', 'accepted')"
51
+ exec "INSERT INTO attr_protected_test_orders(title, workflow_state) VALUES('protected order', 'submitted')"
52
+ end
53
+
54
+ def assert_state(title, expected_state, klass = AttrProtectedTestOrder)
55
+ o = klass.find_by_title(title)
56
+ assert_equal expected_state, o.read_attribute(klass.workflow_column)
57
+ o
58
+ end
59
+
60
+ test 'cannot mass-assign workflow_state if attr_protected' do
61
+ o = AttrProtectedTestOrder.find_by_title('order1')
62
+ assert_equal 'submitted', o.read_attribute(:workflow_state)
63
+ o.update_attributes :workflow_state => 'some_bad_value'
64
+ assert_equal 'submitted', o.read_attribute(:workflow_state)
65
+ o.update_attribute :workflow_state, 'some_overridden_value'
66
+ assert_equal 'some_overridden_value', o.read_attribute(:workflow_state)
67
+ end
68
+
69
+ test 'immediately save the new workflow_state on state machine transition' do
70
+ o = assert_state 'order2', 'accepted'
71
+ assert o.ship!
72
+ assert_state 'order2', 'shipped'
73
+ end
74
+
75
+ test 'persist workflow_state in the db and reload' do
76
+ o = assert_state 'order3', 'accepted'
77
+ assert_equal :accepted, o.current_state.name
78
+ o.ship! # should save in the database, no `o.save!` needed
79
+
80
+ assert_state 'order3', 'shipped'
81
+
82
+ o.reload
83
+ assert_equal 'shipped', o.read_attribute(:workflow_state)
84
+ end
85
+
86
+ test 'default workflow column should be workflow_state' do
87
+ o = assert_state 'order4', 'accepted'
88
+ assert_equal :workflow_state, o.class.workflow_column
89
+ end
90
+
91
+ test 'access workflow specification' do
92
+ assert_equal 3, AttrProtectedTestOrder.workflow_spec.states.length
93
+ assert_equal ['submitted', 'accepted', 'shipped'].sort,
94
+ AttrProtectedTestOrder.workflow_spec.state_names.map{|n| n.to_s}.sort
95
+ end
96
+
97
+ test 'current state object' do
98
+ o = assert_state 'order5', 'accepted'
99
+ assert_equal 'accepted', o.current_state.to_s
100
+ assert_equal 1, o.current_state.events.length
101
+ end
102
+
103
+ end
104
+
data/test/main_test.rb CHANGED
@@ -4,7 +4,7 @@ $VERBOSE = false
4
4
  require 'active_record'
5
5
  require 'sqlite3'
6
6
  require 'workflow'
7
- require 'mocha'
7
+ require 'mocha/setup'
8
8
  require 'stringio'
9
9
  #require 'ruby-debug'
10
10
 
@@ -244,17 +244,6 @@ class MainTest < ActiveRecordTestCase
244
244
  assert !o.shipped?
245
245
  end
246
246
 
247
- unless RUBY_VERSION < '1.9'
248
- test 'compare states' do
249
- o = assert_state 'some order', 'accepted'
250
- assert o.current_state < :shipped
251
- assert o.current_state > :submitted
252
- assert_raise ArgumentError do
253
- o.current_state > :unknown
254
- end
255
- end
256
- end
257
-
258
247
  test 'correct exception for event, that is not allowed in current state' do
259
248
  o = assert_state 'some order', 'accepted'
260
249
  assert_raise Workflow::NoTransitionAllowed do
@@ -289,26 +278,58 @@ class MainTest < ActiveRecordTestCase
289
278
  a.my_transition!(args)
290
279
  end
291
280
 
292
- test '#53 Support for private transition callbacks' do
281
+ test '#53 Support for non public transition callbacks' do
293
282
  args = mock()
294
- args.expects(:log).once
295
- c = Class.new
283
+ args.expects(:log).with('in private callback').once
284
+ args.expects(:log).with('in protected callback in the base class').once
285
+
286
+ b = Class.new # the base class with a protected callback
287
+ b.class_eval do
288
+ protected
289
+ def assign_old(args)
290
+ args.log('in protected callback in the base class')
291
+ end
292
+ end
293
+
294
+ c = Class.new(b) # inheriting class with an additional protected callback
296
295
  c.class_eval do
297
296
  include Workflow
298
297
  workflow do
299
298
  state :new do
300
299
  event :assign, :transitions_to => :assigned
300
+ event :assign_old, :transitions_to => :assigned_old
301
301
  end
302
302
  state :assigned
303
+ state :assigned_old
303
304
  end
304
305
 
305
306
  private
306
307
  def assign(args)
307
- args.log('Assigned')
308
+ args.log('in private callback')
308
309
  end
309
310
  end
311
+
310
312
  a = c.new
311
313
  a.assign!(args)
314
+
315
+ a2 = c.new
316
+ a2.assign_old!(args)
317
+ end
318
+
319
+ test '#58 Limited private transition callback lookup' do
320
+ args = mock()
321
+ c = Class.new
322
+ c.class_eval do
323
+ include Workflow
324
+ workflow do
325
+ state :new do
326
+ event :fail, :transitions_to => :failed
327
+ end
328
+ state :failed
329
+ end
330
+ end
331
+ a = c.new
332
+ a.fail!(args)
312
333
  end
313
334
 
314
335
  test 'Single table inheritance (STI)' do
@@ -417,7 +438,7 @@ class MainTest < ActiveRecordTestCase
417
438
  test 'diagram generation' do
418
439
  begin
419
440
  $stdout = StringIO.new('', 'w')
420
- Workflow::create_workflow_diagram(Order, 'doc')
441
+ Workflow::create_workflow_diagram(Order, '/tmp')
421
442
  assert_match(/open.+\.pdf/, $stdout.string,
422
443
  'PDF should be generate and a hint be given to the user.')
423
444
  ensure
@@ -496,14 +517,14 @@ class MainTest < ActiveRecordTestCase
496
517
  end
497
518
 
498
519
  test 'workflow graph generation' do
499
- Dir.chdir('tmp') do
520
+ Dir.chdir('/tmp') do
500
521
  capture_streams do
501
- Workflow::create_workflow_diagram(Order)
522
+ Workflow::create_workflow_diagram(Order, '/tmp')
502
523
  end
503
524
  end
504
525
  end
505
526
 
506
- test 'workflow graph generation in path with spaces' do
527
+ test 'workflow graph generation in a path with spaces' do
507
528
  `mkdir -p '/tmp/Workflow test'`
508
529
  capture_streams do
509
530
  Workflow::create_workflow_diagram(Order, '/tmp/Workflow test')
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+ require 'workflow'
3
+
4
+ class ComparableStatesOrder
5
+ include Workflow
6
+ workflow do
7
+ state :submitted do
8
+ event :accept, :transitions_to => :accepted, :meta => {:doc_weight => 8} do |reviewer, args|
9
+ end
10
+ end
11
+ state :accepted do
12
+ event :ship, :transitions_to => :shipped
13
+ end
14
+ state :shipped
15
+ end
16
+ end
17
+
18
+ class CompareStatesTest < Test::Unit::TestCase
19
+
20
+ test 'compare states' do
21
+ o = ComparableStatesOrder.new
22
+ o.accept!
23
+ assert_equal :accepted, o.current_state.name
24
+ assert o.current_state < :shipped
25
+ assert o.current_state > :submitted
26
+ assert_raise ArgumentError do
27
+ o.current_state > :unknown
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,62 @@
1
+ require 'test_helper'
2
+ require 'active_record'
3
+ require 'logger'
4
+ require 'sqlite3'
5
+ require 'workflow'
6
+ require 'mocha/setup'
7
+ require 'stringio'
8
+
9
+ ActiveRecord::Migration.verbose = false
10
+
11
+ class PersistenceTestOrder < ActiveRecord::Base
12
+ include Workflow
13
+
14
+ workflow do
15
+ state :submitted do
16
+ event :accept, :transitions_to => :accepted, :meta => {:doc_weight => 8} do |reviewer, args|
17
+ end
18
+ end
19
+ state :accepted do
20
+ event :ship, :transitions_to => :shipped
21
+ end
22
+ state :shipped
23
+ end
24
+
25
+ attr_accessible :title # protecting all the other attributes
26
+
27
+ end
28
+
29
+ PersistenceTestOrder.logger = Logger.new(STDOUT) # active_record 2.3 expects a logger instance
30
+ PersistenceTestOrder.logger.level = Logger::WARN # switch to Logger::DEBUG to see the SQL statements
31
+
32
+ class PersistenceTest < ActiveRecordTestCase
33
+
34
+ def setup
35
+ super
36
+
37
+ ActiveRecord::Schema.define do
38
+ create_table :persistence_test_orders do |t|
39
+ t.string :title, :null => false
40
+ t.string :workflow_state
41
+ end
42
+ end
43
+
44
+ exec "INSERT INTO persistence_test_orders(title, workflow_state) VALUES('order6', 'accepted')"
45
+ end
46
+
47
+ def assert_state(title, expected_state, klass = PersistenceTestOrder)
48
+ o = klass.find_by_title(title)
49
+ assert_equal expected_state, o.read_attribute(klass.workflow_column)
50
+ o
51
+ end
52
+
53
+ test 'ensure other dirty attributes are not saved on state change' do
54
+ o = assert_state 'order6', 'accepted'
55
+ o.title = 'going to change the title'
56
+ assert o.changed?
57
+ o.ship!
58
+ assert o.changed?, 'title should not be saved and the change still stay pending'
59
+ end
60
+
61
+ end
62
+
data/workflow.gemspec CHANGED
@@ -26,5 +26,6 @@ Gem::Specification.new do |gem|
26
26
  gem.add_development_dependency 'activerecord'
27
27
  gem.add_development_dependency 'sqlite3'
28
28
  gem.add_development_dependency 'mocha'
29
+ gem.add_development_dependency 'rake'
29
30
  end
30
31
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.7
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-14 00:00:00.000000000 Z
12
+ date: 2013-02-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rdoc
16
- requirement: &9601480 !ruby/object:Gem::Requirement
16
+ requirement: &7744380 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.12'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *9601480
24
+ version_requirements: *7744380
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &9600720 !ruby/object:Gem::Requirement
27
+ requirement: &7771320 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *9600720
35
+ version_requirements: *7771320
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: activerecord
38
- requirement: &9599800 !ruby/object:Gem::Requirement
38
+ requirement: &7767500 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *9599800
46
+ version_requirements: *7767500
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sqlite3
49
- requirement: &9598500 !ruby/object:Gem::Requirement
49
+ requirement: &7789480 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *9598500
57
+ version_requirements: *7789480
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: mocha
60
- requirement: &9597840 !ruby/object:Gem::Requirement
60
+ requirement: &7788080 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,18 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *9597840
68
+ version_requirements: *7788080
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: &7784180 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *7784180
69
80
  description: ! " Workflow is a finite-state-machine-inspired API for modeling and
70
81
  interacting\n with what we tend to refer to as 'workflow'.\n\n * nice DSL
71
82
  to describe your states, events and transitions\n * robust integration with ActiveRecord
@@ -80,18 +91,23 @@ extra_rdoc_files:
80
91
  - README.markdown
81
92
  files:
82
93
  - .gitignore
94
+ - .travis.yml
83
95
  - Gemfile
84
96
  - MIT-LICENSE
85
97
  - README.markdown
86
98
  - Rakefile
87
- - VERSION
99
+ - gemfiles/Gemfile.rails-2.3.x
88
100
  - lib/workflow.rb
89
101
  - lib/workflow/version.rb
102
+ - test/advanced_examples_test.rb
90
103
  - test/advanced_hooks_and_validation_test.rb
104
+ - test/attr_protected_test.rb
91
105
  - test/before_transition_test.rb
92
106
  - test/couchtiny_example.rb
93
107
  - test/main_test.rb
94
108
  - test/multiple_workflows_test.rb
109
+ - test/new_versions/compare_states_test.rb
110
+ - test/new_versions/persistence_test.rb
95
111
  - test/on_error_test.rb
96
112
  - test/readme_example.rb
97
113
  - test/test_helper.rb
@@ -112,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
112
128
  version: '0'
113
129
  segments:
114
130
  - 0
115
- hash: 2208733943504161358
131
+ hash: 666989584691565007
116
132
  required_rubygems_version: !ruby/object:Gem::Requirement
117
133
  none: false
118
134
  requirements:
@@ -121,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
137
  version: '0'
122
138
  segments:
123
139
  - 0
124
- hash: 2208733943504161358
140
+ hash: 666989584691565007
125
141
  requirements: []
126
142
  rubyforge_project:
127
143
  rubygems_version: 1.8.10
@@ -129,11 +145,15 @@ signing_key:
129
145
  specification_version: 3
130
146
  summary: A replacement for acts_as_state_machine.
131
147
  test_files:
148
+ - test/advanced_examples_test.rb
132
149
  - test/advanced_hooks_and_validation_test.rb
150
+ - test/attr_protected_test.rb
133
151
  - test/before_transition_test.rb
134
152
  - test/couchtiny_example.rb
135
153
  - test/main_test.rb
136
154
  - test/multiple_workflows_test.rb
155
+ - test/new_versions/compare_states_test.rb
156
+ - test/new_versions/persistence_test.rb
137
157
  - test/on_error_test.rb
138
158
  - test/readme_example.rb
139
159
  - test/test_helper.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.8.6