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 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: []