workflow 1.2.0 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9b3ca21163c2fe680f13487bd176530fa13e09b0
4
- data.tar.gz: 3413ad93c300e668a778db3480a7ab11ea3910f1
2
+ SHA256:
3
+ metadata.gz: f86a2a059cb997a5c36395d7f8bab2b572e3468cd7e93819daa37ddb33dd7685
4
+ data.tar.gz: af05dfbb7fbcb238641acb8bad34e78c47afbcbb078dbc71fcd217027b487209
5
5
  SHA512:
6
- metadata.gz: 78329832051f3798e4fc5742eb1ea0f8d10e4f342bcd42e5cf6cb680a7355747e1e12dbcc9a13bc17537843e59e238cc98edd72e67aff106d9b087b2f53901b8
7
- data.tar.gz: 992fe9887c6825b047fbdb28dcc16f10994705fad01aeaedb27266e92469ab4e28f91784d8cb8cb7901b82ce1843b51c03f28abca4b9f8b2550a95b8c88e6c14
6
+ metadata.gz: 79e6e4f70e76e0bce0bfaebfba3e6f20def8b0da4eb9ed6dd8493ae10efe8c5baed5a40ae5d9a7c2c0b1489fdcd2d76445a7f39b8e087998d506635478a9797c
7
+ data.tar.gz: ba55dc2332a66ad167e2522b20fff129dc6eff37778a996acb74c44e931864cf2e321079136a1b41bd96ad590b4fb66ae1ef3b9ad08a0ef9c5a52d61924c7607
@@ -1,8 +1,26 @@
1
- [![Build Status](https://travis-ci.org/geekq/workflow.png?branch=master)](https://travis-ci.org/geekq/workflow) Tested with [different Ruby and Rails versions](https://travis-ci.org/geekq/workflow)
1
+ [![Version ](https://img.shields.io/gem/v/workflow.svg?maxAge=2592000)](https://rubygems.org/gems/workflow)
2
+ [![Build Status ](https://travis-ci.org/geekq/workflow.svg)](https://travis-ci.org/geekq/workflow)
3
+ [![Code Climate ](https://codeclimate.com/github/geekq/workflow/badges/gpa.svg)](https://codeclimate.com/github/geekq/workflow)
4
+ [![Test Coverage](https://codeclimate.com/github/geekq/workflow/badges/coverage.svg)](https://codeclimate.com/github/geekq/workflow/coverage)
2
5
 
3
- Note: you can find documentation for specific workflow rubygem versions at
4
- http://rubygems.org/gems/workflow: select a version (optional, default
5
- is latest release), click "Documentation" link.
6
+ # Workflow
7
+
8
+ Note: you can find documentation for specific workflow rubygem versions
9
+ at http://rubygems.org/gems/workflow : select a version (optional,
10
+ default is latest release), click "Documentation" link. When reading on
11
+ github.com, the README refers to the upcoming release.
12
+
13
+ **Note on ActiveRecord/Rails 4.\*, 5.\* Support:**
14
+
15
+ Since integration with ActiveRecord makes over 90% of the issues and
16
+ maintenance effort, and also to allow for an independent (faster) release cycle
17
+ for Rails support, starting with workflow **version 2.0** the support for
18
+ ActiveRecord (4.\*, 5.\* and newer) is extracted into a separate
19
+ [workflow-activerecord](https://github.com/geekq/workflow-activerecord) gem.
20
+
21
+ You can also implement
22
+ [your own state persistence](https://github.com/geekq/workflow#custom-workflow-state-persistence)
23
+ for ActiveRecord or any other persistence library.
6
24
 
7
25
  What is workflow?
8
26
  -----------------
@@ -106,7 +124,7 @@ Installation
106
124
  gem install workflow
107
125
 
108
126
  **Important**: If you're interested in graphing your workflow state machine, you will also need to
109
- install the `active_support` and `ruby-graphviz` gems.
127
+ install the `activesupport` and `ruby-graphviz` gems.
110
128
 
111
129
  Versions up to and including 1.0.0 are also available as a single file download -
112
130
  [lib/workflow.rb file](https://github.com/geekq/workflow/blob/v1.0.0/lib/workflow.rb).
@@ -424,20 +442,26 @@ representation of the workflow. See below.
424
442
  Conditional event transitions
425
443
  -----------------------------
426
444
 
427
- Conditions are procs or lambdas added to events, like so:
445
+ Conditions can be a "method name symbol" with a corresponding instance method, a `proc` or `lambda` which are added to events, like so:
428
446
 
429
447
  state :off
430
448
  event :turn_on, :transition_to => :on,
431
- :if => proc { |device| device.battery_level > 0 }
449
+ :if => :sufficient_battery_level?
450
+
432
451
  event :turn_on, :transition_to => :low_battery,
433
- :if => proc { |device| device.battery_level > 10 }
452
+ :if => proc { |device| device.battery_level > 0 }
453
+ end
454
+
455
+ # corresponding instance method
456
+ def sufficient_battery_level?
457
+ battery_level > 10
434
458
  end
435
459
 
436
460
  When calling a `device.can_<fire_event>?` check, or attempting a `device.<event>!`, each event is checked in turn:
437
461
 
438
- * With no :if check, proceed as usual.
439
- * If an :if check is present, proceed if it evaluates to true, or drop to the next event.
440
- * If you've run out of events to check (eg. battery_level == 0), then the transition isn't possible.
462
+ * With no `:if` check, proceed as usual.
463
+ * If an `:if` check is present, proceed if it evaluates to true, or drop to the next event.
464
+ * If you've run out of events to check (eg. `battery_level == 0`), then the transition isn't possible.
441
465
 
442
466
 
443
467
  Advanced transition hooks
@@ -603,6 +627,18 @@ Use `Workflow::create_workflow_diagram(class)` in your rake task like:
603
627
  end
604
628
 
605
629
 
630
+ Development Setup
631
+ -----------------
632
+
633
+ sudo apt-get install graphviz # Linux
634
+ brew cask install graphviz # Mac OS
635
+ cd workflow
636
+ gem install bundler
637
+ bundle install
638
+ # run all the tests
639
+ bundle exec rake test
640
+
641
+
606
642
  Earlier versions
607
643
  ----------------
608
644
 
@@ -640,11 +676,29 @@ when using both a block and a callback method for an event, the block executes p
640
676
  Changelog
641
677
  ---------
642
678
 
679
+ ### New in the upcoming version 2.0.0
680
+
681
+ * extract Rails/ActiveRecord integration into a separate gem
682
+ workflow-activerecord
683
+ * Remodel integration removed - needs to be a separate gem
684
+
685
+ ### New in the upcoming version 1.3.0 (never released)
686
+
687
+ * Retiring Ruby 1.8.7 and Rails 2 support #118. If you still need this older
688
+ versions despite security issues and missing updates, you can use
689
+ workflow 1.2.0 or older. In your Gemfile put
690
+
691
+ gem 'workflow', '~> 1.2.0'
692
+
693
+ or when using github source just reference the v1.2.0 tag.
694
+ * improved callback method handling: #113 and #125
695
+
643
696
  ### New in the version 1.2.0
644
697
 
645
698
  * Fix issue #98 protected on\_\* callbacks in Ruby 2
646
699
  * #106 Inherit exceptions from StandardError instead of Exception
647
700
  * #109 Conditional event transitions, contributed by [damncabbage](http://robhoward.id.au/)
701
+ Please note: this introduces incompatible changes to the meta data API, see also #131.
648
702
  * New policy for supporting other databases - extract to separate
649
703
  gems. See the README section above.
650
704
  * #111 Custom Versions of Existing Adapters by [damncabbage](http://robhoward.id.au/)
@@ -1,9 +1,15 @@
1
1
  require 'rubygems'
2
2
 
3
3
  require 'workflow/specification'
4
- require 'workflow/adapters/active_record'
5
4
  require 'workflow/adapters/remodel'
6
5
 
6
+ begin
7
+ require 'ruby-graphviz'
8
+ require 'workflow/draw'
9
+ rescue LoadError => e
10
+ $stderr.puts "Could not load the ruby-graphiz or active_support gems for rendering: #{e.message}"
11
+ end
12
+
7
13
  # See also README.markdown for documentation
8
14
  module Workflow
9
15
  module ClassMethods
@@ -13,7 +19,7 @@ module Workflow
13
19
  if column_name
14
20
  @workflow_state_column_name = column_name.to_sym
15
21
  end
16
- if !@workflow_state_column_name && superclass.respond_to?(:workflow_column)
22
+ if !instance_variable_defined?('@workflow_state_column_name') && superclass.respond_to?(:workflow_column)
17
23
  @workflow_state_column_name = superclass.workflow_column
18
24
  end
19
25
  @workflow_state_column_name ||= :workflow_state
@@ -199,6 +205,7 @@ module Workflow
199
205
  # 1. public callback method or
200
206
  # 2. protected method somewhere in the class hierarchy or
201
207
  # 3. private in the immediate class (parent classes ignored)
208
+ action = action.to_sym
202
209
  self.respond_to?(action) or
203
210
  self.class.protected_method_defined?(action) or
204
211
  self.private_methods(false).map(&:to_sym).include?(action)
@@ -265,13 +272,6 @@ module Workflow
265
272
  # Look for a hook; otherwise detect based on ancestor class.
266
273
  if klass.respond_to?(:workflow_adapter)
267
274
  klass.send :include, klass.workflow_adapter
268
- else
269
- if Object.const_defined?(:ActiveRecord) && klass < ActiveRecord::Base
270
- klass.send :include, Adapter::ActiveRecord
271
- end
272
- if Object.const_defined?(:Remodel) && klass < Adapter::Remodel::Entity
273
- klass.send :include, Adapter::Remodel::InstanceMethods
274
- end
275
275
  end
276
276
  end
277
277
  end
@@ -15,13 +15,8 @@ module Workflow
15
15
  # On transition the new workflow state is immediately saved in the
16
16
  # database.
17
17
  def persist_workflow_state(new_value)
18
- if self.respond_to? :update_column
19
- # Rails 3.1 or newer
20
- update_column self.class.workflow_column, new_value
21
- else
22
- # older Rails; beware of side effect: other (pending) attribute changes will be persisted too
23
- update_attribute self.class.workflow_column, new_value
24
- end
18
+ # Rails 3.1 or newer
19
+ update_column self.class.workflow_column, new_value
25
20
  end
26
21
 
27
22
  private
@@ -42,8 +37,10 @@ module Workflow
42
37
  # Examples:
43
38
  #
44
39
  # Article.with_pending_state # => ActiveRecord::Relation
45
- #
46
- # Example above just adds `where(:state_column_name => 'pending')` to AR query and returns
40
+ # Payment.without_refunded_state # => ActiveRecord::Relation
41
+ #`
42
+ # Example above just adds `where(:state_column_name => 'pending')` or
43
+ # `where.not(:state_column_name => 'pending')` to AR query and returns
47
44
  # ActiveRecord::Relation.
48
45
  module Scopes
49
46
  def self.extended(object)
@@ -55,17 +52,19 @@ module Workflow
55
52
 
56
53
  def workflow_with_scopes(&specification)
57
54
  workflow_without_scopes(&specification)
58
- states = workflow_spec.states.values
59
- eigenclass = class << self; self; end
55
+ states = workflow_spec.states.values
60
56
 
61
57
  states.each do |state|
62
- # Use eigenclass instead of `define_singleton_method`
63
- # to be compatible with Ruby 1.8+
64
- eigenclass.send(:define_method, "with_#{state}_state") do
58
+ define_singleton_method("with_#{state}_state") do
65
59
  where("#{table_name}.#{self.workflow_column.to_sym} = ?", state.to_s)
66
60
  end
61
+
62
+ define_singleton_method("without_#{state}_state") do
63
+ where.not("#{table_name}.#{self.workflow_column.to_sym} = ?", state.to_s)
64
+ end
67
65
  end
68
66
  end
67
+
69
68
  end
70
69
  end
71
70
  end
@@ -1,15 +1,3 @@
1
- begin
2
- require 'rubygems'
3
-
4
- gem 'ruby-graphviz', '~> 1.0.0'
5
- gem 'activesupport'
6
-
7
- require 'graphviz'
8
- require 'active_support/inflector'
9
- rescue LoadError => e
10
- $stderr.puts "Could not load the ruby-graphiz or active_support gems for rendering: #{e.message}"
11
- end
12
-
13
1
  module Workflow
14
2
  module Draw
15
3
 
@@ -41,16 +29,19 @@ module Workflow
41
29
  # @param [String] target_dir Directory, where to save the dot and the pdf files
42
30
  # @param [String] graph_options You can change graph orientation, size etc. See graphviz documentation
43
31
  def self.workflow_diagram(klass, options={})
32
+ # TODO: find some replacement for ActiveSupport::Inflector.tableize
33
+ # or make it usage optional
44
34
  options = {
45
- :name => "#{klass.name.tableize}_workflow".gsub('/', '_'),
35
+ # :name => "#{klass.name.tableize}_workflow".gsub('/', '_'),
36
+ :name => "#{klass.name}_workflow".gsub('/', '_'),
46
37
  :path => '.',
47
38
  :orientation => "landscape",
48
39
  :ratio => "fill",
49
40
  :format => 'png',
50
41
  :font => 'Helvetica'
51
- }.merge options
42
+ }.merge options
52
43
 
53
- graph = ::GraphViz.new('G', :rankdir => options[:orientation] == 'landscape' ? 'LR' : 'TB', :ratio => options[:ratio])
44
+ graph = ::GraphViz.new('G', :rankdir => options[:orientation] == 'landscape' ? 'LR' : 'TB', :ratio => options[:ratio])
54
45
 
55
46
  # Add nodes
56
47
  klass.workflow_spec.states.each do |_, state|
@@ -66,7 +57,7 @@ module Workflow
66
57
  # Generate the graph
67
58
  filename = File.join(options[:path], "#{options[:name]}.#{options[:format]}")
68
59
 
69
- graph.output options[:format] => "'#{filename}'"
60
+ graph.output options[:format] => filename
70
61
 
71
62
  puts "
72
63
  Please run the following to open the generated file:
@@ -1,5 +1,7 @@
1
1
  module Workflow
2
- class TransitionHalted < StandardError
2
+ class Error < StandardError; end
3
+
4
+ class TransitionHalted < Error
3
5
 
4
6
  attr_reader :halted_because
5
7
 
@@ -10,9 +12,9 @@ module Workflow
10
12
 
11
13
  end
12
14
 
13
- class NoTransitionAllowed < StandardError; end
15
+ class NoTransitionAllowed < Error; end
14
16
 
15
- class WorkflowError < StandardError; end
17
+ class WorkflowError < Error; end
16
18
 
17
- class WorkflowDefinitionError < StandardError; end
19
+ class WorkflowDefinitionError < Error; end
18
20
  end
@@ -8,15 +8,23 @@ module Workflow
8
8
  @transitions_to = transitions_to.to_sym
9
9
  @meta = meta
10
10
  @action = action
11
- @condition = if condition.nil? || condition.respond_to?(:call)
11
+ @condition = if condition.nil? || condition.is_a?(Symbol) || condition.respond_to?(:call)
12
12
  condition
13
13
  else
14
- raise TypeError, 'condition must be nil or callable (eg. a proc or lambda)'
14
+ raise TypeError, 'condition must be nil, an instance method name symbol or a callable (eg. a proc or lambda)'
15
15
  end
16
16
  end
17
17
 
18
18
  def condition_applicable?(object)
19
- condition ? condition.call(object) : true
19
+ if condition
20
+ if condition.is_a?(Symbol)
21
+ object.send(condition)
22
+ else
23
+ condition.call(object)
24
+ end
25
+ else
26
+ true
27
+ end
20
28
  end
21
29
 
22
30
  def draw(graph, from_state)
@@ -1,3 +1,3 @@
1
1
  module Workflow
2
- VERSION = "1.2.0"
2
+ VERSION = "2.0.0.pre"
3
3
  end
metadata CHANGED
@@ -1,119 +1,104 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dobriakov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-20 00:00:00.000000000 Z
11
+ date: 2019-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.12'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.12'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.0.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.0.0
41
41
  - !ruby/object:Gem::Dependency
42
- name: activerecord
42
+ name: mocha
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: sqlite3
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: mocha
70
+ name: minitest
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: ruby-graphviz
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: ruby-graphviz
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ~>
102
- - !ruby/object:Gem::Version
103
- version: 1.0.0
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ~>
109
- - !ruby/object:Gem::Version
110
- version: 1.0.0
111
- description: |2
112
- Workflow is a finite-state-machine-inspired API for modeling and interacting
97
+ description: |
98
+ Workflow is a finite-state-machine-inspired API for modeling and interacting
113
99
  with what we tend to refer to as 'workflow'.
114
100
 
115
101
  * nice DSL to describe your states, events and transitions
116
- * robust integration with ActiveRecord and non relational data stores
117
102
  * various hooks for single transitions, entering state etc.
118
103
  * convenient access to the workflow specification: list states, possible events
119
104
  for particular state
@@ -124,16 +109,7 @@ extensions: []
124
109
  extra_rdoc_files:
125
110
  - README.markdown
126
111
  files:
127
- - .gitignore
128
- - .travis.yml
129
- - Gemfile
130
- - MIT-LICENSE
131
112
  - README.markdown
132
- - Rakefile
133
- - gemfiles/Gemfile.rails-2.3.x
134
- - gemfiles/Gemfile.rails-3.x
135
- - gemfiles/Gemfile.rails-4.0
136
- - gemfiles/Gemfile.rails-edge
137
113
  - lib/workflow.rb
138
114
  - lib/workflow/adapters/active_record.rb
139
115
  - lib/workflow/adapters/remodel.rb
@@ -144,26 +120,9 @@ files:
144
120
  - lib/workflow/specification.rb
145
121
  - lib/workflow/state.rb
146
122
  - lib/workflow/version.rb
147
- - orders_workflow.png
148
- - test/active_record_scopes_test.rb
149
- - test/adapter_hook_test.rb
150
- - test/advanced_examples_test.rb
151
- - test/advanced_hooks_and_validation_test.rb
152
- - test/attr_protected_test.rb
153
- - test/before_transition_test.rb
154
- - test/couchtiny_example.rb
155
- - test/inheritance_test.rb
156
- - test/main_test.rb
157
- - test/multiple_workflows_test.rb
158
- - test/new_versions/compare_states_test.rb
159
- - test/new_versions/persistence_test.rb
160
- - test/on_error_test.rb
161
- - test/readme_example.rb
162
- - test/test_helper.rb
163
- - test/without_active_record_test.rb
164
- - workflow.gemspec
165
123
  homepage: http://www.geekq.net/workflow/
166
- licenses: []
124
+ licenses:
125
+ - MIT
167
126
  metadata: {}
168
127
  post_install_message:
169
128
  rdoc_options: []
@@ -171,34 +130,18 @@ require_paths:
171
130
  - lib
172
131
  required_ruby_version: !ruby/object:Gem::Requirement
173
132
  requirements:
174
- - - '>='
133
+ - - ">="
175
134
  - !ruby/object:Gem::Version
176
- version: '0'
135
+ version: '2.3'
177
136
  required_rubygems_version: !ruby/object:Gem::Requirement
178
137
  requirements:
179
- - - '>='
138
+ - - ">"
180
139
  - !ruby/object:Gem::Version
181
- version: '0'
140
+ version: 1.3.1
182
141
  requirements: []
183
142
  rubyforge_project:
184
- rubygems_version: 2.0.14
143
+ rubygems_version: 2.7.6
185
144
  signing_key:
186
145
  specification_version: 4
187
146
  summary: A replacement for acts_as_state_machine.
188
- test_files:
189
- - test/active_record_scopes_test.rb
190
- - test/adapter_hook_test.rb
191
- - test/advanced_examples_test.rb
192
- - test/advanced_hooks_and_validation_test.rb
193
- - test/attr_protected_test.rb
194
- - test/before_transition_test.rb
195
- - test/couchtiny_example.rb
196
- - test/inheritance_test.rb
197
- - test/main_test.rb
198
- - test/multiple_workflows_test.rb
199
- - test/new_versions/compare_states_test.rb
200
- - test/new_versions/persistence_test.rb
201
- - test/on_error_test.rb
202
- - test/readme_example.rb
203
- - test/test_helper.rb
204
- - test/without_active_record_test.rb
147
+ test_files: []