workflow 1.2.0 → 2.0.0.pre
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 +5 -5
- data/README.markdown +65 -11
- data/lib/workflow.rb +9 -9
- data/lib/workflow/adapters/active_record.rb +13 -14
- data/lib/workflow/draw.rb +7 -16
- data/lib/workflow/errors.rb +6 -4
- data/lib/workflow/event.rb +11 -3
- data/lib/workflow/version.rb +1 -1
- metadata +28 -85
- data/.gitignore +0 -20
- data/.travis.yml +0 -27
- data/Gemfile +0 -3
- data/MIT-LICENSE +0 -20
- data/Rakefile +0 -30
- data/gemfiles/Gemfile.rails-2.3.x +0 -11
- data/gemfiles/Gemfile.rails-3.x +0 -11
- data/gemfiles/Gemfile.rails-4.0 +0 -13
- data/gemfiles/Gemfile.rails-edge +0 -13
- data/orders_workflow.png +0 -0
- data/test/active_record_scopes_test.rb +0 -49
- data/test/adapter_hook_test.rb +0 -52
- data/test/advanced_examples_test.rb +0 -84
- data/test/advanced_hooks_and_validation_test.rb +0 -119
- data/test/attr_protected_test.rb +0 -107
- data/test/before_transition_test.rb +0 -36
- data/test/couchtiny_example.rb +0 -46
- data/test/inheritance_test.rb +0 -60
- data/test/main_test.rb +0 -584
- data/test/multiple_workflows_test.rb +0 -84
- data/test/new_versions/compare_states_test.rb +0 -32
- data/test/new_versions/persistence_test.rb +0 -62
- data/test/on_error_test.rb +0 -52
- data/test/readme_example.rb +0 -37
- data/test/test_helper.rb +0 -39
- data/test/without_active_record_test.rb +0 -54
- data/workflow.gemspec +0 -32
data/.gitignore
DELETED
data/.travis.yml
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
before_install:
|
2
|
-
- sudo apt-get install -qq graphviz
|
3
|
-
|
4
|
-
rvm:
|
5
|
-
- 2.0.0
|
6
|
-
gemfile:
|
7
|
-
- gemfiles/Gemfile.rails-edge
|
8
|
-
|
9
|
-
matrix:
|
10
|
-
include:
|
11
|
-
# legacy build: Ruby 1.8.7, Rails 2.3, less features, smaller test set
|
12
|
-
- rvm: 1.8.7
|
13
|
-
gemfile: gemfiles/Gemfile.rails-2.3.x
|
14
|
-
# running a smaller test set for old Rails and Ruby
|
15
|
-
script: rake test_without_new_versions
|
16
|
-
|
17
|
-
- rvm: 1.9.3
|
18
|
-
gemfile: gemfiles/Gemfile.rails-3.x
|
19
|
-
|
20
|
-
- rvm: 2.0.0
|
21
|
-
gemfile: gemfiles/Gemfile.rails-3.x
|
22
|
-
|
23
|
-
- rvm: 2.0.0
|
24
|
-
gemfile: gemfiles/Gemfile.rails-4.0
|
25
|
-
|
26
|
-
- rvm: 2.1.0
|
27
|
-
gemfile: gemfiles/Gemfile.rails-3.x
|
data/Gemfile
DELETED
data/MIT-LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright (c) 2008-2009 Vodafone
|
2
|
-
Copyright (c) 2007-2008 Ryan Allen, FlashDen Pty Ltd
|
3
|
-
|
4
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
-
of this software and associated documentation files (the "Software"), to deal
|
6
|
-
in the Software without restriction, including without limitation the rights
|
7
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
-
copies of the Software, and to permit persons to whom the Software is
|
9
|
-
furnished to do so, subject to the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be included in
|
12
|
-
all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
-
THE SOFTWARE.
|
data/Rakefile
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake/testtask'
|
3
|
-
require 'rdoc/task'
|
4
|
-
|
5
|
-
require 'bundler'
|
6
|
-
Bundler.setup
|
7
|
-
|
8
|
-
task :default => [:test]
|
9
|
-
|
10
|
-
require 'rake'
|
11
|
-
Rake::TestTask.new do |t|
|
12
|
-
t.libs << 'test'
|
13
|
-
t.verbose = true
|
14
|
-
t.warning = true
|
15
|
-
t.test_files = FileList['test/*_test.rb'] + FileList['test/new_versions/*_test.rb']
|
16
|
-
end
|
17
|
-
|
18
|
-
Rake::TestTask.new do |t|
|
19
|
-
t.name = 'test_without_new_versions'
|
20
|
-
t.libs << 'test'
|
21
|
-
t.verbose = true
|
22
|
-
t.warning = true
|
23
|
-
t.pattern = 'test/*_test.rb'
|
24
|
-
end
|
25
|
-
|
26
|
-
Rake::RDocTask.new do |rdoc|
|
27
|
-
rdoc.rdoc_files.include("lib/**/*.rb")
|
28
|
-
rdoc.options << "-S"
|
29
|
-
end
|
30
|
-
|
data/gemfiles/Gemfile.rails-3.x
DELETED
data/gemfiles/Gemfile.rails-4.0
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
source "http://rubygems.org"
|
2
|
-
|
3
|
-
group :development do
|
4
|
-
gem "minitest", "< 5.0.0" # 5.0.0 introduced incompatible changes renaming all the classes
|
5
|
-
gem "rdoc", ">= 3.12"
|
6
|
-
gem "bundler", ">= 1.0.0"
|
7
|
-
gem "activerecord", "~>4.0"
|
8
|
-
gem 'protected_attributes'
|
9
|
-
gem "sqlite3"
|
10
|
-
gem "mocha"
|
11
|
-
gem "rake"
|
12
|
-
gem "ruby-graphviz", "~> 1.0.0"
|
13
|
-
end
|
data/gemfiles/Gemfile.rails-edge
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
source "http://rubygems.org"
|
2
|
-
|
3
|
-
group :development do
|
4
|
-
gem "minitest", "< 5.0.0" # 5.0.0 introduced incompatible changes renaming all the classes
|
5
|
-
gem "rdoc", ">= 3.12"
|
6
|
-
gem "bundler", ">= 1.0.0"
|
7
|
-
gem "activerecord"
|
8
|
-
gem "sqlite3"
|
9
|
-
gem "mocha"
|
10
|
-
gem "rake"
|
11
|
-
gem "ruby-graphviz", "~> 1.0.0"
|
12
|
-
gem 'protected_attributes'
|
13
|
-
end
|
data/orders_workflow.png
DELETED
Binary file
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
-
|
3
|
-
$VERBOSE = false
|
4
|
-
require 'active_record'
|
5
|
-
require 'sqlite3'
|
6
|
-
require 'workflow'
|
7
|
-
|
8
|
-
ActiveRecord::Migration.verbose = false
|
9
|
-
|
10
|
-
class Article < ActiveRecord::Base
|
11
|
-
include Workflow
|
12
|
-
|
13
|
-
workflow do
|
14
|
-
state :new
|
15
|
-
state :accepted
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class ActiveRecordScopesTest < ActiveRecordTestCase
|
20
|
-
|
21
|
-
def setup
|
22
|
-
super
|
23
|
-
|
24
|
-
ActiveRecord::Schema.define do
|
25
|
-
create_table :articles do |t|
|
26
|
-
t.string :title
|
27
|
-
t.string :body
|
28
|
-
t.string :blame_reason
|
29
|
-
t.string :reject_reason
|
30
|
-
t.string :workflow_state
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def assert_state(title, expected_state, klass = Order)
|
36
|
-
o = klass.find_by_title(title)
|
37
|
-
assert_equal expected_state, o.read_attribute(klass.workflow_column)
|
38
|
-
o
|
39
|
-
end
|
40
|
-
|
41
|
-
test 'have "with_new_state" scope' do
|
42
|
-
assert_respond_to Article, :with_new_state
|
43
|
-
end
|
44
|
-
|
45
|
-
test 'have "with_accepted_state" scope' do
|
46
|
-
assert_respond_to Article, :with_accepted_state
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
data/test/adapter_hook_test.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
-
require 'workflow'
|
3
|
-
class AdapterHookTest < ActiveRecordTestCase
|
4
|
-
test 'hook to choose adapter' do
|
5
|
-
|
6
|
-
ActiveRecord::Schema.define do
|
7
|
-
create_table(:examples) { |t| t.string :workflow_state }
|
8
|
-
end
|
9
|
-
|
10
|
-
class DefaultAdapter < ActiveRecord::Base
|
11
|
-
self.table_name = :examples
|
12
|
-
include Workflow
|
13
|
-
workflow do
|
14
|
-
state(:initial) { event :progress, :transitions_to => :last }
|
15
|
-
state(:last)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class ChosenByHookAdapter < ActiveRecord::Base
|
20
|
-
self.table_name = :examples
|
21
|
-
attr_reader :foo
|
22
|
-
def self.workflow_adapter
|
23
|
-
Module.new do
|
24
|
-
def load_workflow_state
|
25
|
-
@foo if defined?(@foo)
|
26
|
-
end
|
27
|
-
def persist_workflow_state(new_value)
|
28
|
-
@foo = new_value
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
include Workflow
|
34
|
-
workflow do
|
35
|
-
state(:initial) { event :progress, :transitions_to => :last }
|
36
|
-
state(:last)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
default = DefaultAdapter.create
|
41
|
-
assert default.initial?
|
42
|
-
default.progress!
|
43
|
-
assert default.last?
|
44
|
-
assert DefaultAdapter.find(default.id).last?, 'should have persisted via ActiveRecord'
|
45
|
-
|
46
|
-
hook = ChosenByHookAdapter.create
|
47
|
-
assert hook.initial?
|
48
|
-
hook.progress!
|
49
|
-
assert_equal hook.foo, 'last', 'should have "persisted" with custom adapter'
|
50
|
-
assert ChosenByHookAdapter.find(hook.id).initial?, 'should not have persisted via ActiveRecord'
|
51
|
-
end
|
52
|
-
end
|
@@ -1,84 +0,0 @@
|
|
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.flat.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.push(
|
37
|
-
revert_event_name,
|
38
|
-
Workflow::Event.new(revert_event_name, state)
|
39
|
-
)
|
40
|
-
|
41
|
-
# Add methods for revert events
|
42
|
-
Article.module_eval do
|
43
|
-
define_method "#{revert_event_name}!".to_sym do |*args|
|
44
|
-
process_event!(revert_event_name, *args)
|
45
|
-
end
|
46
|
-
define_method "can_#{revert_event_name}?" do
|
47
|
-
return self.current_state.events.include?(revert_event_name)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
a = Article.new
|
55
|
-
assert(a.new?, "should start with the 'new' state")
|
56
|
-
a.submit!
|
57
|
-
assert(a.awaiting_review?, "should now be in 'awaiting_review' state")
|
58
|
-
assert_equal(['revert_submit', 'review'], a.current_state.events.keys.map(&:to_s).sort)
|
59
|
-
a.revert_submit! # this method is added by our meta programming magic above
|
60
|
-
assert(a.new?, "should now be back in the 'new' state")
|
61
|
-
end
|
62
|
-
|
63
|
-
test '#92 Load workflow specification' do
|
64
|
-
c = Class.new
|
65
|
-
c.class_eval do
|
66
|
-
include Workflow
|
67
|
-
end
|
68
|
-
|
69
|
-
# build a Specification (you can load it from yaml file too)
|
70
|
-
myspec = Workflow::Specification.new do
|
71
|
-
state :one do
|
72
|
-
event :dynamic_transition, :transitions_to => :one_a
|
73
|
-
end
|
74
|
-
state :one_a
|
75
|
-
end
|
76
|
-
|
77
|
-
c.send :assign_workflow, myspec
|
78
|
-
|
79
|
-
a = c.new
|
80
|
-
a.dynamic_transition!(1)
|
81
|
-
assert a.one_a?, 'Expected successful transition to a new state'
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
@@ -1,119 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
-
|
3
|
-
$VERBOSE = false
|
4
|
-
require 'active_record'
|
5
|
-
require 'sqlite3'
|
6
|
-
require 'workflow'
|
7
|
-
|
8
|
-
ActiveRecord::Migration.verbose = false
|
9
|
-
|
10
|
-
# Transition based validation
|
11
|
-
# ---------------------------
|
12
|
-
# If you are using ActiveRecord you might want to define different validations
|
13
|
-
# for different transitions. There is a `validates_presence_of` hook that let's
|
14
|
-
# you specify the attributes that need to be present for an successful transition.
|
15
|
-
# If the object is not valid at the end of the transition event the transition
|
16
|
-
# is halted and a TransitionHalted exception is thrown.
|
17
|
-
#
|
18
|
-
# Here is a sample that illustrates how to use the presence validation:
|
19
|
-
# (use case suggested by http://github.com/southdesign)
|
20
|
-
class Article < ActiveRecord::Base
|
21
|
-
include Workflow
|
22
|
-
workflow do
|
23
|
-
state :new do
|
24
|
-
event :accept, :transitions_to => :accepted, :meta => {:validates_presence_of => [:title, :body]}
|
25
|
-
event :reject, :transitions_to => :rejected
|
26
|
-
end
|
27
|
-
state :accepted do
|
28
|
-
event :blame, :transitions_to => :blamed, :meta => {:validates_presence_of => [:title, :body, :blame_reason]}
|
29
|
-
event :delete, :transitions_to => :deleted
|
30
|
-
end
|
31
|
-
state :rejected do
|
32
|
-
event :delete, :transitions_to => :deleted
|
33
|
-
end
|
34
|
-
state :blamed do
|
35
|
-
event :delete, :transitions_to => :deleted
|
36
|
-
end
|
37
|
-
state :deleted do
|
38
|
-
event :accept, :transitions_to => :accepted
|
39
|
-
end
|
40
|
-
|
41
|
-
on_transition do |from, to, triggering_event, *event_args|
|
42
|
-
if self.class.superclass.to_s.split("::").first == "ActiveRecord"
|
43
|
-
singleton = class << self; self end
|
44
|
-
validations = Proc.new {}
|
45
|
-
|
46
|
-
meta = Article.workflow_spec.states[from].events[triggering_event].first.meta
|
47
|
-
fields_to_validate = meta[:validates_presence_of]
|
48
|
-
if fields_to_validate
|
49
|
-
validations = Proc.new {
|
50
|
-
errors.add_on_blank(fields_to_validate) if fields_to_validate
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
singleton.send :define_method, :validate_for_transition, &validations
|
55
|
-
validate_for_transition
|
56
|
-
halt! "Event[#{triggering_event}]'s transitions_to[#{to}] is not valid." unless self.errors.empty?
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
class AdvancedHooksAndValidationTest < ActiveRecordTestCase
|
63
|
-
|
64
|
-
def setup
|
65
|
-
super
|
66
|
-
|
67
|
-
ActiveRecord::Schema.define do
|
68
|
-
create_table :articles do |t|
|
69
|
-
t.string :title
|
70
|
-
t.string :body
|
71
|
-
t.string :blame_reason
|
72
|
-
t.string :reject_reason
|
73
|
-
t.string :workflow_state
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
exec "INSERT INTO articles(title, body, blame_reason, reject_reason, workflow_state) VALUES('new1', NULL, NULL, NULL, 'new')"
|
78
|
-
exec "INSERT INTO articles(title, body, blame_reason, reject_reason, workflow_state) VALUES('new2', 'some content', NULL, NULL, 'new')"
|
79
|
-
exec "INSERT INTO articles(title, body, blame_reason, reject_reason, workflow_state) VALUES('accepted1', 'some content', NULL, NULL, 'accepted')"
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
def assert_state(title, expected_state, klass = Order)
|
84
|
-
o = klass.find_by_title(title)
|
85
|
-
assert_equal expected_state, o.read_attribute(klass.workflow_column)
|
86
|
-
o
|
87
|
-
end
|
88
|
-
|
89
|
-
test 'deny transition from new to accepted because of the missing presence of the body' do
|
90
|
-
a = Article.find_by_title('new1');
|
91
|
-
assert_raise Workflow::TransitionHalted do
|
92
|
-
a.accept!
|
93
|
-
end
|
94
|
-
assert_state 'new1', 'new', Article
|
95
|
-
end
|
96
|
-
|
97
|
-
test 'allow transition from new to accepted because body is present this time' do
|
98
|
-
a = Article.find_by_title('new2');
|
99
|
-
assert a.accept!
|
100
|
-
assert_state 'new2', 'accepted', Article
|
101
|
-
end
|
102
|
-
|
103
|
-
test 'allow transition from accepted to blamed because of a blame_reason' do
|
104
|
-
a = Article.find_by_title('accepted1');
|
105
|
-
a.blame_reason = "Provocant thesis"
|
106
|
-
assert a.blame!
|
107
|
-
assert_state 'accepted1', 'blamed', Article
|
108
|
-
end
|
109
|
-
|
110
|
-
test 'deny transition from accepted to blamed because of no blame_reason' do
|
111
|
-
a = Article.find_by_title('accepted1');
|
112
|
-
assert_raise Workflow::TransitionHalted do
|
113
|
-
assert a.blame!
|
114
|
-
end
|
115
|
-
assert_state 'accepted1', 'accepted', Article
|
116
|
-
end
|
117
|
-
|
118
|
-
end
|
119
|
-
|