step_machine 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bef3877ea59535b62e02fe0bf0abfb5fb04a3ed1
4
+ data.tar.gz: 4d5489faf7ff54e3939dc6b061f43cf94b179b6c
5
+ SHA512:
6
+ metadata.gz: 5e87e732a0d7dfa89573a2d972bf47f62a8b1ea91e5449473f715415189e04fd7f9dff48b73425dc25e0801dd109d7c655420d25d59eed611b40beb1904f21dd
7
+ data.tar.gz: 0b31754b61675dc2646b4c2dc4656686007f0a8a2988b7ac1f772fd7267d00d3fc958278ab82021a082e442d2082a6513ba9f0f1031aaa7ffda990646c268b77
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.sublime-project
19
+ *.sublime-workspace
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # ruby '1.9.3'
4
+ # Specify your gem's dependencies in step_machine.gemspec
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem 'rspec'
9
+ gem 'guard-rspec'
10
+ gem 'pry'
11
+ gem 'simplecov'
12
+ end
data/Guardfile ADDED
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Rafael Vettori and Geison Biazus
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # StepMachine
2
+
3
+ step_machine is a simple gem for executing code based in steps. Each step can be validated and if a step fails, the execution is aborted.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'step_machine'
10
+
11
+ or
12
+
13
+ gem 'step_machine', git: git@bitbucket.org:geisonbiazus/step_machine.git
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ ## Usage
20
+
21
+ ## Creating and running steps:
22
+ include StepMachine
23
+
24
+ step(:step_1) do
25
+ # code for step 1
26
+ end
27
+
28
+ step(:step_2) do
29
+ # code for step 2
30
+ end
31
+
32
+ run_steps
33
+
34
+ This code will run the steps in the created order
35
+
36
+ ## Changing the execution order
37
+
38
+ step(:step_1).next_step = step(:step_2)
39
+
40
+ or:
41
+
42
+ step(:step_1).next_step do
43
+ step(:step_2)
44
+ end
45
+
46
+ ## Validating steps
47
+
48
+ step(:step_1).validate do |step|
49
+ step.result == "OK"
50
+ end
51
+
52
+ step(step_1).validate(/^OK/)
53
+
54
+ step(step_1).validate('OK')
55
+
56
+ ## Validating steps error message
57
+
58
+ step(:step_1).validate do |step|
59
+ step.result == "OK"
60
+ step.errors << 'This is a array error message forced to false validate'
61
+ end
62
+
63
+ step(step_1).errors({}) << 'This is a hash error message forced to false validate'
64
+
65
+ step(step_1).errors('') << 'This is a string error message forced to false validate'
66
+
67
+ ## Callbacks
68
+
69
+ on_step_failure do |f|
70
+ f.go_to :step_2
71
+ end
72
+
73
+ on_step_failure :only => [:step_2] do |f|
74
+ f.restart
75
+ end
76
+
77
+ on_step_failure :except => [:step_1] do |f|
78
+ if contition
79
+ f.repeat
80
+ else
81
+ f.continue
82
+ end
83
+ end
84
+
85
+ before_each_step do |step|
86
+ # code
87
+ end
88
+
89
+ after_each_step do |step|
90
+ # code
91
+ end
92
+
93
+ ## Executing code if a step runs successful
94
+
95
+ step(:step_1).success do |step|
96
+ # code
97
+ end
98
+
99
+ ## Conditional Steps
100
+
101
+ step(:step_1).condition do
102
+ true
103
+ end
104
+
105
+ ## Executing a step depending on other step condition
106
+
107
+ step(:step_2) do
108
+ # code
109
+ end.condition do
110
+ step(:step_1).performed?
111
+ end
112
+
113
+ ## Grouping steps
114
+
115
+ group :group_1 do
116
+
117
+ step :step_1 do
118
+ #code
119
+ end
120
+
121
+ step :step_2 do
122
+ #code
123
+ end
124
+
125
+ end
126
+
127
+ step :step_3 do
128
+ #code
129
+ end
130
+
131
+ run_steps( {:group => :group_1} ) # only the steps 1 and 2 will be performed
132
+
133
+ ## Group with condition
134
+
135
+ group(:group_1)
136
+
137
+ step(:step_2) do
138
+ # code
139
+ end
140
+
141
+ end.condition do
142
+ step(:step_1).performed?
143
+ end
144
+
145
+ run_steps # only if was performed
146
+
147
+ ## Execute from and/or upto defined step
148
+
149
+ step :step_1 { ... }
150
+ step :step_2 { ... }
151
+ step :step_3 { ... }
152
+ step :step_4 { ... }
153
+ run_steps :upto => :step_2 # should execute :step_1 end :step_2
154
+ run_steps :from => :step_3 # should execute :step_3 end :step_4
155
+ run_steps :from => :step2, :upto => :step_3 # should execute :step_2 end :step_3
156
+
157
+ ## Contributing
158
+
159
+ 1. Fork it
160
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
161
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
162
+ 4. Push to the branch (`git push origin my-new-feature`)
163
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+
3
+ require "step_machine/version"
4
+ require "step_machine/group"
5
+ require "step_machine/step"
6
+ require "step_machine/runner"
7
+
8
+ module StepMachine
9
+
10
+ module ClassMethods
11
+ end
12
+
13
+ module InstanceMethods
14
+
15
+ def group(name, &block)
16
+ @step_machine_runner ||= Runner.new
17
+ @step_machine_runner.group(name, &block)
18
+ end
19
+
20
+ def step(name, &block)
21
+ @step_machine_runner ||= Runner.new
22
+ @step_machine_runner.step(name, &block)
23
+ end
24
+
25
+ def on_step_failure(options = {}, &block)
26
+ @step_machine_runner.on_step_failure(options, &block)
27
+ end
28
+
29
+ def before_each_step(options = {}, &block)
30
+ @step_machine_runner.before_each_step(options, &block)
31
+ end
32
+
33
+ def after_each_step(options = {}, &block)
34
+ @step_machine_runner.after_each_step(options, &block)
35
+ end
36
+
37
+ def run_steps(options = {})
38
+ @step_machine_runner.run(options)
39
+ end
40
+
41
+ def first_step(step)
42
+ @step_machine_runner.first_step = step
43
+ end
44
+
45
+ def run_status
46
+ @step_machine_runner.status
47
+ end
48
+
49
+ def failed_step
50
+ @step_machine_runner.failed_step
51
+ end
52
+
53
+ end
54
+
55
+ def self.included(receiver)
56
+ receiver.extend ClassMethods
57
+ receiver.send :include, InstanceMethods
58
+ end
59
+ end
@@ -0,0 +1,17 @@
1
+ module StepMachine
2
+
3
+ class Group
4
+ attr_accessor :name, :first_step
5
+ attr_reader :condition_block
6
+
7
+ def initialize(name)
8
+ @name = name
9
+ end
10
+
11
+ def condition(&block)
12
+ @condition_block = block if block
13
+ self
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,201 @@
1
+ module StepMachine
2
+ class Runner
3
+
4
+ attr_accessor :first_step, :continue, :next_step, :times_to_repeat, :repeat_what
5
+ attr_reader :status, :failed_step
6
+
7
+ def initialize
8
+ @steps = []
9
+ @groups = []
10
+ @failure_treatments = []
11
+ @before_each_step = []
12
+ @after_each_step = []
13
+ @times_to_repeat = -1
14
+ end
15
+
16
+ def step(name, &block)
17
+ step = get_step(name) || create_step(name)
18
+ step.block = block if block
19
+ @first_step ||= step
20
+ @next_step ||= @first_step
21
+
22
+ step
23
+ end
24
+
25
+ def group(name)
26
+ return nil if name.nil?
27
+ @current_group = group = @groups.detect {|g| g.name == name} || create_group(name)
28
+ yield if block_given?
29
+ @current_group = nil
30
+ group
31
+ end
32
+
33
+ def on_step_failure(options = {}, &block)
34
+ @failure_treatments << FailureTreatment.new(self, block, options)
35
+ end
36
+
37
+ def before_each_step(options = {}, &block)
38
+ @before_each_step << options.merge(:block => block)
39
+ end
40
+
41
+ def after_each_step(options = {}, &block)
42
+ @after_each_step << options.merge(:block => block)
43
+ end
44
+
45
+ def first_step=(step)
46
+ @next_step = @first_step = step
47
+ end
48
+
49
+ def run(options = {})
50
+ if group = group(options[:group])
51
+ assign_group_first_step(group)
52
+ return if @next_step.group != group
53
+ end
54
+
55
+ assign_from_step(options[:from]) unless options[:from].nil?
56
+
57
+ @continue = nil
58
+ step = @next_step
59
+
60
+ @status ||= :success
61
+
62
+ execute_before_each_step(step)
63
+
64
+ unless step.perform
65
+ @failed_step = step
66
+
67
+ return repeat if repeat?
68
+
69
+ execute_step_failures(step)
70
+
71
+ return run if @continue
72
+ @status = :failure
73
+ return
74
+ end
75
+ execute_after_each_step(step)
76
+
77
+ return if step.name == options[:upto]
78
+
79
+ run(options) if @next_step = step.next
80
+ end
81
+
82
+ private
83
+
84
+ def assign_from_step(step)
85
+ if !@from_first_step
86
+ @next_step = get_step(step)
87
+ @from_first_step = true
88
+ end
89
+ end
90
+
91
+ def assign_group_first_step(group)
92
+ if !@group_first_step
93
+ @next_step = group.first_step
94
+ @group_first_step = true
95
+ end
96
+ end
97
+
98
+ def execute_before_each_step(step)
99
+ @before_each_step.each do |before|
100
+ next if before.has_key?(:only) && !before[:only].include?(step.name)
101
+ next if before.has_key?(:except) && before[:except].include?(step.name)
102
+ before[:block].call(step)
103
+ end
104
+ end
105
+
106
+ def execute_after_each_step(step)
107
+ @after_each_step.each do |after|
108
+ next if after.has_key?(:only) && !after[:only].include?(step.name)
109
+ next if after.has_key?(:except) && after[:except].include?(step.name)
110
+ after[:block].call(step)
111
+ end
112
+ end
113
+
114
+ def execute_step_failures(step)
115
+ @failure_treatments.each do |failure_treatment|
116
+ failure_treatment.treat(step)
117
+ end
118
+ end
119
+
120
+ def get_step(name)
121
+ @steps.find { |step| step.name == name }
122
+ end
123
+
124
+ def create_step(name)
125
+ step = Step.new(name)
126
+ step.group = @current_group
127
+ @current_group.first_step ||= step if @current_group
128
+ @steps << step
129
+ @steps[-2].next_step = step if @steps.length > 1
130
+ step
131
+ end
132
+
133
+ def create_group(name)
134
+ group = Group.new(name)
135
+ @groups << group
136
+ group
137
+ end
138
+
139
+ def repeat?
140
+ @times_to_repeat >= 0
141
+ end
142
+
143
+ def repeat
144
+ @times_to_repeat -= 1
145
+
146
+ if @times_to_repeat == -1
147
+ @status = :failure
148
+ return
149
+ end
150
+
151
+ @next_step = @repeat_what == :process ? @first_step : @failed_step
152
+ return run
153
+ end
154
+
155
+
156
+ class FailureTreatment
157
+ attr_accessor :step
158
+
159
+ def initialize(runner, block, options)
160
+ @runner = runner
161
+ @block = block
162
+ @options = options
163
+ end
164
+
165
+ def treat(step)
166
+ return if @options.has_key?(:only) && !@options[:only].include?(step.name)
167
+ return if @options.has_key?(:except) && @options[:except].include?(step.name)
168
+ @step = step
169
+
170
+ @block.call(self)
171
+ end
172
+
173
+ def go_to(step_name)
174
+ @runner.next_step = @runner.step(step_name)
175
+ @runner.continue = true
176
+ end
177
+
178
+ def repeat
179
+ go_to(@step.name)
180
+ @runner.repeat_what = :step
181
+ self
182
+ end
183
+
184
+ def continue
185
+ go_to(@step.next.name)
186
+ end
187
+
188
+ def restart
189
+ go_to(@runner.first_step.name)
190
+ @runner.repeat_what = :process
191
+ self
192
+ end
193
+
194
+ def times(number)
195
+ @runner.times_to_repeat = number - 1
196
+ end
197
+
198
+ end
199
+
200
+ end
201
+ end