rao-service_chain 0.0.38.pre → 0.0.43.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
2
  SHA256:
3
- metadata.gz: 8e5e8c17080f335d7dca5868c7ebb9b634ac4875dc3f0da34a980636bfefcb73
4
- data.tar.gz: b0e57dd2954bfbbf1f4b2baeacc1f21a7f4e5163296547eea4073b61ad5ef65b
3
+ metadata.gz: 1ed5e8922014983a8ba799164bcd4531d2d433aa7a5136a48e4d7f3bda26c738
4
+ data.tar.gz: ca3cfb9f4572e269291863ac884ce32c59e608b0083b60037fcf7258d4afd7a1
5
5
  SHA512:
6
- metadata.gz: 85191653db150a484fc6ec8af2146fc8d1d042711e775a45243ce7165a543753e1c18f3f06bba02b79151b0c8c1de27312837a5a42cd7d477ebf638084880907
7
- data.tar.gz: 2b31b9257e8b961eca6f51c27084d72471b39dc8aa8b15a329f9568f137227f0e0b73902d89d5c455c0306ff0c89e17006d6a246b6fc4896ed9fe97c180bdf4a
6
+ metadata.gz: bc7b363310554f003fd52cc890d93aab7746d25d15ae1a8386ba5bca27c8589f39fc9345a371daa4a050bcb40a835460c316a8d455f0a4e19c8830014a6776b4
7
+ data.tar.gz: 95a9504526c028767e6978b9c5f9f78b477e422214ec1e9d02de27a21566024176b7f2377b02f7f368e1d4af9e02f9c8037147f6cebb05c104a575aaf5170755
@@ -0,0 +1,6 @@
1
+ module Rao
2
+ module ServiceChain
3
+ module Aasm
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,264 @@
1
+
2
+ module Rao
3
+ module ServiceChain
4
+ module Aasm
5
+ class Base
6
+ include ::AASM
7
+
8
+ def initialize(options = {})
9
+ options.each do |k,v|
10
+ send("#{k}=", v)
11
+ end
12
+ end
13
+
14
+ module ServiceConcern
15
+ extend ActiveSupport::Concern
16
+
17
+ class_methods do
18
+ def service_module_name
19
+ nil
20
+ end
21
+ end
22
+
23
+ def service_class_to_state(service_class)
24
+ service_class.name.demodulize.underscore.to_sym
25
+ end
26
+
27
+ def state_to_service_class(state)
28
+ "#{self.class.service_module_name}#{state.to_s.camelize}".constantize
29
+ end
30
+ end
31
+
32
+ include ServiceConcern
33
+
34
+ module StepConcern
35
+ extend ActiveSupport::Concern
36
+
37
+ def actual_step=(service_class)
38
+ aasm.current_state = service_class_to_state(service_class)
39
+ end
40
+
41
+ def actual_step
42
+ return nil if %i(started finished).include?(aasm.current_state)
43
+ wrap(
44
+ state_to_service_class(aasm.current_state),
45
+ completed_if: aasm.states.find { |s| s.name == aasm.current_state }.options[:completed_if],
46
+ router: aasm.states.find { |s| s.name == aasm.current_state }.options[:router],
47
+ url: aasm.states.find { |s| s.name == aasm.current_state }.options[:url],
48
+ )
49
+ end
50
+
51
+ def previous_steps
52
+ current_state = aasm.current_state
53
+ o = []
54
+ i = 0
55
+ while(i < 1000) do
56
+ previous_event = aasm.events.select{ |e| e.name == :previous }.first
57
+ return [] unless previous_event.respond_to?(:transitions)
58
+ targets = previous_event.transitions.select{ |t|
59
+ # targets = aasm.events(permitted: true).select{ |e| e.name == :next }.first.transitions.select{ |t|
60
+ t.from == current_state
61
+ }.select{ |t|
62
+ guards = t.instance_variable_get(:@guards)
63
+ if guards.empty?
64
+ true
65
+ else
66
+ guards.map { |g| send(g) }.all?
67
+ end
68
+ }.map { |t|
69
+ {
70
+ t.to => {
71
+ display: (t.options[:display].presence || -> { true }),
72
+ completed_if: aasm.states.find { |s| s.name == t.to }.options[:completed_if],
73
+ router: aasm.states.find { |s| s.name == t.to }.options[:router],
74
+ url: aasm.states.find { |s| s.name == t.to }.options[:url],
75
+ }
76
+ }
77
+ }
78
+ break if targets.empty? || %i(started finished).include?(targets.first.first[0])
79
+ o << wrap(state_to_service_class(targets.first.first[0]), targets.first.first[1])
80
+ current_state = targets.first.first[0]
81
+ i = i + 1
82
+ end
83
+ o.reverse.compact
84
+ end
85
+
86
+ def next_steps
87
+ current_state = aasm.current_state
88
+ o = []
89
+ i = 0
90
+ while(i < 1000) do
91
+ previous_event = aasm.events.select{ |e| e.name == :next }.first
92
+ return [] unless previous_event.respond_to?(:transitions)
93
+ targets = previous_event.transitions.select{ |t|
94
+ # targets = aasm.events(permitted: true).select{ |e| e.name == :next }.first.transitions.select{ |t|
95
+ t.from == current_state
96
+ }.select{ |t|
97
+ guards = t.instance_variable_get(:@guards)
98
+ if guards.empty?
99
+ true
100
+ else
101
+ guards.map { |g| send(g) }.all?
102
+ end
103
+ }.map { |t|
104
+ {
105
+ t.to => {
106
+ display: (t.options[:display].presence || -> { true }),
107
+ completed_if: aasm.states.find { |s| s.name == t.to }.options[:completed_if],
108
+ router: aasm.states.find { |s| s.name == t.to }.options[:router],
109
+ url: aasm.states.find { |s| s.name == t.to }.options[:url],
110
+ }
111
+ }
112
+ }
113
+ break if targets.empty? || %i(started finished).include?(targets.first.first[0])
114
+ o << wrap(state_to_service_class(targets.first.first[0]), targets.first.first[1])
115
+ current_state = targets.first.first[0]
116
+ i = i + 1
117
+ end
118
+ o.compact
119
+ end
120
+
121
+ def steps
122
+ # aasm.states.map(&:name).map { |s| wrap(state_to_service_class(s)) }
123
+ o = []
124
+
125
+ #walk backwards
126
+ # current_state = aasm.current_state
127
+ # i = 0
128
+ # while(i < 1000) do
129
+ # targets = aasm.events.select{ |e| e.name == :previous }.first.transitions.select{ |t|
130
+ # # targets = aasm.events(permitted: true).select{ |e| e.name == :previous }.first.transitions.select{ |t|
131
+ # t.from == current_state
132
+ # }.select{ |t|
133
+ # guards = t.instance_variable_get(:@guards)
134
+ # if guards.empty?
135
+ # true
136
+ # else
137
+ # guards.map { |g| send(g) }.all?
138
+ # end
139
+ # }.map { |t| t.to }
140
+ # break if targets.empty?
141
+ # o << wrap(state_to_service_class(targets.first))
142
+ # current_state = targets.first
143
+ # i = i + 1
144
+ # end
145
+
146
+ # o.reverse!
147
+
148
+ o << self.previous_steps
149
+
150
+ # add actual state
151
+ o << self.actual_step unless self.actual_step.nil?
152
+ # o << wrap(state_to_service_class(aasm.current_state))
153
+
154
+ # walk forward
155
+ o << self.next_steps
156
+ # current_state = aasm.current_state
157
+ # i = 0
158
+ # while(i < 1000) do
159
+ # targets = aasm.events.select{ |e| e.name == :next }.first.transitions.select{ |t|
160
+ # # targets = aasm.events(permitted: true).select{ |e| e.name == :next }.first.transitions.select{ |t|
161
+ # t.from == current_state
162
+ # }.select{ |t|
163
+ # guards = t.instance_variable_get(:@guards)
164
+ # if guards.empty?
165
+ # true
166
+ # else
167
+ # guards.map { |g| send(g) }.all?
168
+ # end
169
+ # }.map { |t| {t.to => { display: (t.options[:display].presence || -> { true }) } } }
170
+ # break if targets.empty?
171
+ # o << wrap(state_to_service_class(targets.first.first[0]), targets.first.first[1])
172
+ # current_state = targets.first.first[0]
173
+ # i = i + 1
174
+ # end
175
+ o.flatten
176
+ end
177
+
178
+ def step_count
179
+ steps.size
180
+ end
181
+
182
+ def completed_steps
183
+ self.steps.collect { |s| s.completed? ? s : nil }.compact
184
+ end
185
+
186
+ def pending_steps
187
+ self.steps.collect { |s| s.pending? ? s : nil }.compact
188
+ end
189
+
190
+ private
191
+
192
+ def wrap(service, options = {})
193
+ wrapper_class = Rao::ServiceChain::Step::Base
194
+ if service.is_a?(wrapper_class)
195
+ service
196
+ else
197
+ wrapper_class.new(options.merge(service: service, chain: self))
198
+ end
199
+ end
200
+ end
201
+
202
+ include StepConcern
203
+
204
+ module StepOrderConcern
205
+ extend ActiveSupport::Concern
206
+
207
+ def before_actual?(step)
208
+ return false if self.actual_step.nil?
209
+ return false if (si = step_index(wrap(step))).nil?
210
+ self.actual_step_index > si
211
+ end
212
+
213
+ def after_actual?(step)
214
+ return false if self.actual_step.nil?
215
+ return false if (si = step_index(wrap(step))).nil?
216
+ self.actual_step_index < si
217
+ end
218
+
219
+ def step_index(step)
220
+ self.steps.map(&:service).index(step.try(:service))
221
+ end
222
+
223
+ def actual_step_index
224
+ self.steps.map(&:service).index(self.actual_step.try(:service))
225
+ end
226
+
227
+ def next_step
228
+ self.next_steps.first
229
+ # return nil if self.actual_step_index.nil?
230
+ # return nil if self.actual_step_index + 1 >= self.step_count
231
+ # self.steps[self.actual_step_index + 1]
232
+ end
233
+
234
+ def previous_step
235
+ self.previous_steps.last
236
+ # return nil if self.actual_step_index.nil?
237
+ # return nil if self.actual_step_index - 1 < 0
238
+ # self.steps[self.actual_step_index - 1]
239
+ end
240
+
241
+ def next_step_url(options = {})
242
+ context = options.delete(:context)
243
+ self.next_step.url(context)
244
+ end
245
+ end
246
+
247
+ include StepOrderConcern
248
+
249
+ module SerializationConcern
250
+ extend ActiveSupport::Concern
251
+
252
+ def to_hash(context = nil)
253
+ {
254
+ actual_step: self.actual_step.to_hash(context),
255
+ steps: self.steps.map { |s| s.to_hash(context) }
256
+ }
257
+ end
258
+ end
259
+
260
+ include SerializationConcern
261
+ end
262
+ end
263
+ end
264
+ end
@@ -0,0 +1,151 @@
1
+ module Rao
2
+ module ServiceChain
3
+ class Base
4
+ attr_accessor :steps
5
+ attr_accessor :actual_step
6
+
7
+ def initialize(options = {})
8
+ options.each do |key, value|
9
+ self.send("#{key}=", value)
10
+ end
11
+ if @actual_step.present?
12
+ actual_service = unwrap(@actual_step)
13
+ @actual_step = find_step_by_service(actual_service)
14
+ end
15
+ end
16
+
17
+ def wrap_actual_step!
18
+ @actual_step = wrap(@actual_step)
19
+ end
20
+
21
+ def steps=(steps)
22
+ @steps = steps.map { |s| wrap(s) }
23
+ end
24
+
25
+ def steps
26
+ raise "Child class responsiblity"
27
+ end
28
+
29
+ def step_index(step)
30
+ self.steps.map(&:service).index(step.try(:service))
31
+ end
32
+
33
+ def service_index(service)
34
+ self.steps.map(&:service).index(service)
35
+ end
36
+
37
+ def find_step_by_service(service)
38
+ self.steps[(service_index(service))]
39
+ end
40
+
41
+ def actual_step_index
42
+ self.steps.map(&:service).index(self.actual_step.try(:service))
43
+ end
44
+
45
+ def step_count
46
+ self.steps.size
47
+ end
48
+
49
+ def previous_step_index
50
+ self.steps.map(&:service).index(self.previous_step.try(:service))
51
+ end
52
+
53
+ def next_step_index
54
+ self.steps.map(&:service).index(self.next_step.try(:service))
55
+ end
56
+
57
+ def previous_step
58
+ return nil if self.actual_step_index.nil?
59
+ return nil if self.actual_step_index - 1 < 0
60
+ self.steps[self.actual_step_index - 1]
61
+ end
62
+
63
+ def previous_steps
64
+ return [] if self.actual_step_index.nil?
65
+ return [] if self.actual_step_index == 0
66
+ self.steps[0..(self.actual_step_index - 1)]
67
+ end
68
+
69
+ def next_step
70
+ if self.actual_step.try(:next_step).respond_to?(:call)
71
+ find_step_by_service(self.actual_step.next_step.call(self.actual_step))
72
+ else
73
+ return nil if self.actual_step_index.nil?
74
+ return nil if self.actual_step_index + 1 >= self.step_count
75
+ self.steps[self.actual_step_index + 1]
76
+ end
77
+ end
78
+
79
+ def next_steps
80
+ return [] if self.actual_step_index.nil?
81
+ self.steps[(self.actual_step_index + 1)..-1]
82
+ end
83
+
84
+ def next_step?
85
+ !!next_step
86
+ end
87
+
88
+ def previous_step?
89
+ !!previous_step
90
+ end
91
+
92
+ def next_step_url(options = {})
93
+ context = options.delete(:context)
94
+ self.next_step.url(context)
95
+ end
96
+
97
+ def steps_with_urls(context)
98
+ self.steps.map { |s| s.url(context); s }
99
+ end
100
+
101
+ def to_hash(context = nil)
102
+ {
103
+ actual_step: self.actual_step.to_hash(context),
104
+ steps: self.steps.map { |s| s.to_hash(context) }
105
+ }
106
+ end
107
+
108
+ def completed_steps
109
+ self.steps.collect { |s| s.completed? ? s : nil }.compact
110
+ end
111
+
112
+ def pending_steps
113
+ self.steps.collect { |s| s.pending? ? s : nil }.compact
114
+ end
115
+
116
+ def before_actual?(step)
117
+ return false if self.actual_step.nil?
118
+ return false if (si = step_index(wrap(step))).nil?
119
+ self.actual_step_index > si
120
+ end
121
+
122
+ def after_actual?(step)
123
+ return false if self.actual_step.nil?
124
+ return false if (si = step_index(wrap(step))).nil?
125
+ self.actual_step_index < si
126
+ end
127
+
128
+ private
129
+
130
+ def wrap(service, options = {})
131
+ if service.is_a?(wrapper_base_class)
132
+ service
133
+ else
134
+ wrapper_base_class.new(options.merge(service: service, chain: self))
135
+ end
136
+ end
137
+
138
+ def unwrap(step_or_service)
139
+ if step_or_service.is_a?(wrapper_base_class)
140
+ step_or_service.service
141
+ else
142
+ step_or_service
143
+ end
144
+ end
145
+
146
+ def wrapper_base_class
147
+ Rao::ServiceChain::Step::Base
148
+ end
149
+ end
150
+ end
151
+ end
@@ -2,7 +2,7 @@ module Rao
2
2
  module ServiceChain
3
3
  module Step
4
4
  class Base
5
- attr_accessor :service, :service_name, :label, :chain
5
+ attr_accessor :service, :service_name, :label, :chain, :router
6
6
 
7
7
  def initialize(options = {})
8
8
  @service = options.delete(:service)
@@ -12,12 +12,13 @@ module Rao
12
12
  @service_name = @service.try(:name)
13
13
  @label = service.try(:model_name).try(:human)
14
14
  @url = options.delete(:url)
15
+ @router = options.delete(:router) || :main_app
15
16
  end
16
17
 
17
18
  def url(context = nil)
18
19
  return nil if context.nil?
19
20
  return context.instance_exec(@service, &@url) if @url.respond_to?(:call)
20
- @url ||= context.url_for([:new, @service, only_path: true])
21
+ @url ||= context.send(router).url_for([:new, @service, only_path: true])
21
22
  end
22
23
 
23
24
  def completed?
@@ -25,6 +26,25 @@ module Rao
25
26
  @chain.instance_exec(@service, &@completed_if)
26
27
  end
27
28
 
29
+ def render_as_completed?(options = {})
30
+ render_previous_steps_as_pending = options.dig(:previous_steps, :render_as_pending)
31
+ render_next_step_as_pending = options.dig(:next_steps, :render_as_pending)
32
+
33
+ if @chain.before_actual?(self)
34
+ if render_previous_steps_as_pending
35
+ completed?
36
+ else
37
+ true
38
+ end
39
+ else
40
+ if render_next_step_as_pending
41
+ false
42
+ else
43
+ completed?
44
+ end
45
+ end
46
+ end
47
+
28
48
  def pending?
29
49
  !completed?
30
50
  end
@@ -20,17 +20,23 @@ module Rao
20
20
  #
21
21
  def render_progress(service_chain, options = {})
22
22
  return if service_chain.nil?
23
-
24
- options.reverse_merge!(
25
- theme: :bootstrap4,
26
- link_next_steps: true,
27
- link_actual_step: false,
28
- link_previous_steps: true
29
- )
23
+
24
+ options = default_options.deep_merge(options)
30
25
  theme = options.delete(:theme)
31
26
 
32
27
  c.render partial: "rao/service_chain/application_view_helper/render_progress/#{theme}", locals: { service_chain: service_chain, options: options }
33
28
  end
29
+
30
+ private
31
+
32
+ def default_options
33
+ {
34
+ theme: :bootstrap4,
35
+ next_steps: { render_as_pending: false, link: true },
36
+ actual_step: { link: false },
37
+ previous_steps: { render_as_pending: true, link: true }
38
+ }
39
+ end
34
40
  end
35
41
  end
36
42
  end
@@ -8,19 +8,19 @@
8
8
  %span.wizard-step-marker.rounded-circle.bg-primary.text-white
9
9
  %i.fas.fa-play
10
10
  %span.wizard-step-label
11
- - if options[:link_actual_step]
11
+ - if options.dig(:actual_step, :link)
12
12
  = link_to(step.label, step.url(self))
13
13
  - else
14
14
  = step.label
15
15
  - else
16
- - if step.completed?
17
- %span.wizard-step-marker.rounded-circle.bg-success.text-white
16
+ - if step.render_as_completed?(options)
17
+ %span.wizard-step-marker.rounded-circle.bg-success.text-white.render-completed
18
18
  %i.fas.fa-check
19
19
  - else
20
- %span.wizard-step-marker.rounded-circle.bg-secondary.text-white
20
+ %span.wizard-step-marker.rounded-circle.bg-secondary.text-white.render-pending
21
21
  %i.fas.fa-circle
22
22
  %span.wizard-step-label
23
- - if (service_chain.before_actual?(step) && options[:link_previous_steps]) || (service_chain.after_actual?(step) && options[:link_next_steps])
23
+ - if (service_chain.before_actual?(step) && options.dig(:previous_steps, :link)) || (service_chain.after_actual?(step) && options.dig(:next_steps, :link))
24
24
  = link_to(step.label, step.url(self))
25
25
  - else
26
26
  = step.label
@@ -1,3 +1,4 @@
1
+ require "aasm"
1
2
  require "haml-rails"
2
3
 
3
4
  require "rao"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rao-service_chain
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.38.pre
4
+ version: 0.0.43.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto Vasquez Angel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-13 00:00:00.000000000 Z
11
+ date: 2020-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: aasm
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: haml-rails
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -164,7 +178,10 @@ files:
164
178
  - app/assets/stylesheets/rao/service_chain/application.css
165
179
  - app/assets/stylesheets/rao/service_chain/application/wizard.css
166
180
  - app/concerns/rao/service/chain/controller_concern.rb
181
+ - app/service_chains/rao/service_chain/aasm.rb
182
+ - app/service_chains/rao/service_chain/aasm/base.rb
167
183
  - app/service_chains/rao/service_chain/base.rb
184
+ - app/service_chains/rao/service_chain/base~.rb
168
185
  - app/service_steps/rao/service_chain/step/base.rb
169
186
  - app/view_helpers/rao/service_chain/application_view_helper.rb
170
187
  - app/views/rao/service_chain/application_view_helper/render_progress/_bootstrap4.html.haml
@@ -195,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
212
  - !ruby/object:Gem::Version
196
213
  version: 1.3.1
197
214
  requirements: []
198
- rubygems_version: 3.0.6
215
+ rubygems_version: 3.1.4
199
216
  signing_key:
200
217
  specification_version: 4
201
218
  summary: Service Chains for Ruby on Rails.