workflow-join 0.1.1 → 0.2.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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +6 -9
- data/Rakefile +9 -2
- data/lib/workflow/join.rb +55 -32
- data/lib/workflow/join/active_record.rb +43 -0
- data/lib/workflow/join/active_record/pending_callbacks.rb +31 -0
- data/lib/workflow/join/active_record/pending_transitions.rb +41 -0
- data/lib/workflow/join/simple.rb +11 -0
- data/lib/workflow/join/simple/pending_callbacks.rb +23 -0
- data/lib/workflow/join/simple/pending_transitions.rb +36 -0
- data/lib/workflow/join/version.rb +1 -1
- data/workflow-join.gemspec +2 -0
- metadata +35 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40f7e69d9114f772e7a3057bdbbfedc974dd786d
|
4
|
+
data.tar.gz: 779672bcd9063eb69d6b5400ebe7318957df3669
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 684b92e932e55d231c37c57f49a43715b7369ad2fae41e8fca5ce1e56d64f3820b5241af20c845fc1423cc1361f428c2644b4fef82277c90edc2859b33b8fb86
|
7
|
+
data.tar.gz: 9c60b3ff584e173d0a91d9e2a9a5e7dbca12b1e707f4105081fe9882276f93de6c2f2b3944d63e99f0f952a9ec9df772043c77f196c6ab8041967e9442e43a98
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2016-09-
|
3
|
+
# on 2016-09-16 13:15:05 +0200 using RuboCop version 0.42.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -16,12 +16,7 @@ Lint/BlockAlignment:
|
|
16
16
|
|
17
17
|
# Offense count: 1
|
18
18
|
Metrics/AbcSize:
|
19
|
-
Max:
|
20
|
-
|
21
|
-
# Offense count: 1
|
22
|
-
# Configuration parameters: CountComments.
|
23
|
-
Metrics/MethodLength:
|
24
|
-
Max: 46
|
19
|
+
Max: 57
|
25
20
|
|
26
21
|
# Offense count: 1
|
27
22
|
# Cop supports --auto-correct.
|
@@ -37,18 +32,20 @@ Style/MutableConstant:
|
|
37
32
|
Exclude:
|
38
33
|
- 'lib/workflow/join/version.rb'
|
39
34
|
|
40
|
-
# Offense count:
|
35
|
+
# Offense count: 2
|
41
36
|
# Cop supports --auto-correct.
|
42
37
|
# Configuration parameters: PreferredDelimiters.
|
43
38
|
Style/PercentLiteralDelimiters:
|
44
39
|
Exclude:
|
40
|
+
- 'spec/workflow/active_record_spec.rb'
|
45
41
|
- 'spec/workflow/join_spec.rb'
|
46
42
|
|
47
|
-
# Offense count:
|
43
|
+
# Offense count: 2
|
48
44
|
# Cop supports --auto-correct.
|
49
45
|
Style/RescueModifier:
|
50
46
|
Exclude:
|
51
47
|
- 'lib/workflow/join.rb'
|
48
|
+
- 'lib/workflow/join/active_record/pending_callbacks.rb'
|
52
49
|
|
53
50
|
# Offense count: 4
|
54
51
|
# Cop supports --auto-correct.
|
data/Rakefile
CHANGED
@@ -15,10 +15,17 @@ rescue Bundler::BundlerError => e
|
|
15
15
|
exit e.status_code
|
16
16
|
end
|
17
17
|
|
18
|
-
desc 'Tests'
|
18
|
+
desc 'Tests w/ActiveRecord'
|
19
19
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
20
20
|
spec.rspec_opts = '-Ispec'
|
21
21
|
# spec.rcov = true
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
desc 'Tests wo/ActiveRecord'
|
25
|
+
RSpec::Core::RakeTask.new(:spec_simple) do |spec|
|
26
|
+
ENV['USE_SIMPLE_PERSISTENCE'] = 'true'
|
27
|
+
spec.rspec_opts = '-Ispec'
|
28
|
+
# spec.rcov = true
|
29
|
+
end
|
30
|
+
|
31
|
+
task default: [:spec, :spec_simple]
|
data/lib/workflow/join.rb
CHANGED
@@ -1,57 +1,79 @@
|
|
1
1
|
require 'workflow'
|
2
2
|
require 'workflow/join/version'
|
3
3
|
|
4
|
+
if ENV['USE_SIMPLE_PERSISTENCE'] == 'true'
|
5
|
+
require 'workflow/join/simple'
|
6
|
+
puts "☆ Using simple mode (no persistence,) due to ‘ENV['USE_SIMPLE_PERSISTENCE']’"
|
7
|
+
else
|
8
|
+
begin
|
9
|
+
require 'active_record'
|
10
|
+
require 'workflow/join/active_record'
|
11
|
+
rescue LoadError => e
|
12
|
+
require 'workflow/join/simple'
|
13
|
+
puts "★ Error requiring ActiveRecord (message: “#{e.message}”.) Will run in simple mode (no persistence.)"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
4
17
|
Workflow::ClassMethods.prepend(Module.new do
|
5
18
|
def workflow(&specification)
|
6
19
|
# extend instances
|
7
20
|
prepend(Module.new do # this should be safe, since there could not be two subsequent workflow DSL
|
8
|
-
|
21
|
+
if Workflow::Join.const_defined?('ActiveRecord')
|
22
|
+
include Workflow::Join::ActiveRecord # AR pending transitions and callbacks implementation
|
23
|
+
else
|
24
|
+
include Workflow::Join::Simple # simple pending transitions and callbacks implementation
|
25
|
+
end
|
26
|
+
|
9
27
|
def guards!
|
28
|
+
spec.instance_variable_set(:@original_before_transition_proc, spec.before_transition_proc) \
|
29
|
+
unless spec.instance_variable_defined?(:@original_before_transition_proc)
|
30
|
+
|
10
31
|
λλs = spec.guards.map do |inner, outers|
|
11
32
|
outers.map do |getter, state|
|
12
33
|
guard! inner, getter, state
|
13
|
-
end
|
34
|
+
end.compact
|
14
35
|
end.flatten
|
15
|
-
|
36
|
+
|
37
|
+
(original_before_transition_proc = spec.instance_variable_get(:@original_before_transition_proc)) && \
|
38
|
+
λλs << original_before_transition_proc
|
16
39
|
spec.before_transition_proc = ->(from, to, name, *args) { λλs.each { |λ| λ.(from, to, name, *args) } }
|
17
40
|
end
|
18
41
|
|
19
42
|
def guard!(inner, getter, state)
|
20
|
-
slave = getter.call(self)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
true
|
31
|
-
rescue
|
32
|
-
false # no transition no cry
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
super(old_state, event, *args) rescue nil # no super no cry
|
43
|
+
return if getter.nil? || (slave = getter.call(self)).nil? # I’ll be back, hasta la vista, baby :)
|
44
|
+
|
45
|
+
slave.class.send :define_method, "on_#{state}_entry".to_sym do |old_state, event, *args|
|
46
|
+
pending_callbacks.each do |master|
|
47
|
+
master.reload if master.respond_to?(:reload)
|
48
|
+
next unless master.pending_transitions?
|
49
|
+
master.try_pending_transitions!
|
50
|
+
# halted is automagically removed after successful transition
|
51
|
+
# the line below is unneeded
|
52
|
+
# master.halted = master.pending_transitions?
|
37
53
|
end
|
38
|
-
|
54
|
+
super(old_state, event, *args) rescue nil # no super no cry
|
55
|
+
end
|
56
|
+
|
39
57
|
lambda do |_, to, name, *|
|
58
|
+
slave.reload if slave.respond_to?(:reload)
|
40
59
|
if to.to_sym == inner && !slave.send("#{state}?".to_sym)
|
41
|
-
|
42
|
-
|
60
|
+
pending_transition! name
|
61
|
+
slave.pending_callback!(self)
|
43
62
|
halt("Waiting for guard workflow to enter “:#{state}” state")
|
44
63
|
end
|
45
64
|
end
|
46
65
|
end
|
47
66
|
end)
|
48
67
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
68
|
+
if respond_to?(:after_commit)
|
69
|
+
after_commit { guards! }
|
70
|
+
else
|
71
|
+
singleton_class.prepend(Module.new do
|
72
|
+
def new(*)
|
73
|
+
super.tap(&:guards!)
|
74
|
+
end
|
75
|
+
end)
|
76
|
+
end
|
55
77
|
|
56
78
|
super
|
57
79
|
end
|
@@ -61,7 +83,7 @@ module Workflow
|
|
61
83
|
module Join
|
62
84
|
GUARD_PARAMS_ERROR = 'Either guard instance variable name or a code block is required'.freeze
|
63
85
|
GUARD_POINTCUT_ERROR = 'Both :inner and :outer states are required'.freeze
|
64
|
-
GUARD_IS_NOT_WORKFLOW = 'Guard given must be a workflow instance'.freeze
|
86
|
+
GUARD_IS_NOT_WORKFLOW = 'Guard given must be a workflow instance, was: “%s”'.freeze
|
65
87
|
|
66
88
|
def guards
|
67
89
|
@guards ||= {}
|
@@ -79,10 +101,11 @@ module Workflow
|
|
79
101
|
case
|
80
102
|
when /\A@/ =~ g.to_s && host.instance_variable_defined?(g)
|
81
103
|
host.instance_variable_get(g)
|
82
|
-
when host.methods.include?(g) && host.method(g).arity
|
104
|
+
when host.methods.include?(g) && host.method(g).arity <= 0
|
83
105
|
host.send g
|
84
106
|
end.tap do |guard_instance|
|
85
|
-
fail Workflow::WorkflowDefinitionError, GUARD_IS_NOT_WORKFLOW
|
107
|
+
fail Workflow::WorkflowDefinitionError, GUARD_IS_NOT_WORKFLOW % guard_instance \
|
108
|
+
unless guard_instance.nil? || guard_instance.is_a?(Workflow)
|
86
109
|
end
|
87
110
|
end
|
88
111
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'workflow/join/active_record/pending_transitions'
|
2
|
+
require 'workflow/join/active_record/pending_callbacks'
|
3
|
+
|
4
|
+
module Workflow
|
5
|
+
module Join
|
6
|
+
module ActiveRecord
|
7
|
+
ENSURE_COLUMNS = lambda do |model, *columns|
|
8
|
+
columns.reduce(true) do |memo, column|
|
9
|
+
next memo if model.column_names.include?(column.to_s)
|
10
|
+
|
11
|
+
::ActiveRecord::Base.connection.execute(
|
12
|
+
"ALTER TABLE #{model.table_name} ADD #{column} VARCHAR(255)"
|
13
|
+
)
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
include PendingTransitions
|
19
|
+
include PendingCallbacks
|
20
|
+
|
21
|
+
def self.included(base)
|
22
|
+
base.singleton_class.send :define_method, :prepended do |model|
|
23
|
+
fail LoadError, "This module might be included in ActiveRecord::Base instances only (#{base} given.)" \
|
24
|
+
unless model < ::ActiveRecord::Base
|
25
|
+
|
26
|
+
unless ENSURE_COLUMNS.call(model, :workflow_pending_transitions, :workflow_pending_callbacks)
|
27
|
+
fail LoadError, <<-MSG
|
28
|
+
|
29
|
+
=======================================================================================
|
30
|
+
This is an intended fail, next time the class is requested, it’ll be loaded properly!
|
31
|
+
To avoid this one should explicitly specify columns:
|
32
|
+
— workflow_pending_transitions,
|
33
|
+
— workflow_pending_callbacks
|
34
|
+
in all models, that are willing to use joined workflows.
|
35
|
+
=======================================================================================
|
36
|
+
|
37
|
+
MSG
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Workflow
|
2
|
+
module Join
|
3
|
+
module ActiveRecord
|
4
|
+
# table.column :workflow_pending_callbacks, :string
|
5
|
+
module PendingCallbacks
|
6
|
+
def pending_callbacks
|
7
|
+
workflow_pending_callbacks.to_s.split(';').map do |wpc|
|
8
|
+
c, id = wpc.split(',')
|
9
|
+
Kernel.const_get(c).find(id) rescue nil
|
10
|
+
end.compact
|
11
|
+
end
|
12
|
+
|
13
|
+
def pending_callbacks!(value)
|
14
|
+
pcs = case value
|
15
|
+
when Array then value.map { |instance| [instance.class.name, instance.id].join(',') }.join(';')
|
16
|
+
when String, Symbol then value.to_s
|
17
|
+
end
|
18
|
+
update_column :workflow_pending_callbacks, pcs
|
19
|
+
end
|
20
|
+
|
21
|
+
def pending_callbacks?
|
22
|
+
!pending_callbacks.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def pending_callback!(value)
|
26
|
+
pending_callbacks!(pending_callbacks | [value])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Workflow
|
2
|
+
module Join
|
3
|
+
module ActiveRecord
|
4
|
+
# table.column :workflow_pending_transitions, :string
|
5
|
+
module PendingTransitions
|
6
|
+
def pending_transitions
|
7
|
+
workflow_pending_transitions.to_s.split(',').map(&:to_sym)
|
8
|
+
end
|
9
|
+
|
10
|
+
def pending_transitions!(value)
|
11
|
+
pts = case value
|
12
|
+
when Array then value.map(&:to_s).join(',')
|
13
|
+
when String, Symbol then value.to_s
|
14
|
+
end
|
15
|
+
update_column :workflow_pending_transitions, pts
|
16
|
+
end
|
17
|
+
|
18
|
+
def pending_transitions?
|
19
|
+
!pending_transitions.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def pending_transition!(value)
|
23
|
+
pending_transitions!(pending_transitions | [value])
|
24
|
+
end
|
25
|
+
|
26
|
+
def try_pending_transitions!
|
27
|
+
pending_transitions!(pending_transitions.reject do |transition|
|
28
|
+
begin
|
29
|
+
respond_to?("can_#{transition}?") && \
|
30
|
+
public_send("can_#{transition}?") && \
|
31
|
+
public_send("#{transition}!".to_sym) && \
|
32
|
+
true
|
33
|
+
rescue
|
34
|
+
false # no transition no cry
|
35
|
+
end
|
36
|
+
end)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Workflow
|
2
|
+
module Join
|
3
|
+
module Simple
|
4
|
+
module PendingCallbacks
|
5
|
+
def pending_callbacks
|
6
|
+
@pending_callbacks ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
def pending_callbacks!(value)
|
10
|
+
@pending_callbacks = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def pending_callbacks?
|
14
|
+
!pending_callbacks.empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
def pending_callback!(value)
|
18
|
+
pending_callbacks!(pending_callbacks | [value])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Workflow
|
2
|
+
module Join
|
3
|
+
module Simple
|
4
|
+
module PendingTransitions
|
5
|
+
def pending_transitions
|
6
|
+
@pending_transitions ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
def pending_transitions!(value)
|
10
|
+
@pending_transitions = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def pending_transitions?
|
14
|
+
!pending_transitions.empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
def pending_transition!(value)
|
18
|
+
pending_transitions!(pending_transitions | [value])
|
19
|
+
end
|
20
|
+
|
21
|
+
def try_pending_transitions!
|
22
|
+
pending_transitions.reject! do |transition|
|
23
|
+
begin
|
24
|
+
respond_to?("can_#{transition}?") && \
|
25
|
+
public_send("can_#{transition}?") && \
|
26
|
+
public_send("#{transition}!".to_sym) && \
|
27
|
+
true
|
28
|
+
rescue
|
29
|
+
false # no transition no cry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/workflow-join.gemspec
CHANGED
@@ -29,6 +29,8 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_development_dependency 'rspec'
|
30
30
|
spec.add_development_dependency 'rubocop'
|
31
31
|
spec.add_development_dependency 'pry'
|
32
|
+
spec.add_development_dependency 'sqlite3'
|
32
33
|
|
33
34
|
spec.add_dependency 'workflow', '~> 1.2'
|
35
|
+
spec.add_dependency 'activerecord'
|
34
36
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workflow-join
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksei Matiushkin
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: workflow
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +108,20 @@ dependencies:
|
|
94
108
|
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '1.2'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: activerecord
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
97
125
|
description: Workflow extension that allows to fork workflows with other workflows
|
98
126
|
and join them at specific states.
|
99
127
|
email:
|
@@ -115,6 +143,12 @@ files:
|
|
115
143
|
- bin/console
|
116
144
|
- bin/setup
|
117
145
|
- lib/workflow/join.rb
|
146
|
+
- lib/workflow/join/active_record.rb
|
147
|
+
- lib/workflow/join/active_record/pending_callbacks.rb
|
148
|
+
- lib/workflow/join/active_record/pending_transitions.rb
|
149
|
+
- lib/workflow/join/simple.rb
|
150
|
+
- lib/workflow/join/simple/pending_callbacks.rb
|
151
|
+
- lib/workflow/join/simple/pending_transitions.rb
|
118
152
|
- lib/workflow/join/version.rb
|
119
153
|
- workflow-join.gemspec
|
120
154
|
homepage: https://github.com/am-kantox/workflow-join
|