rung 0.0.1.pre.alpha
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 +7 -0
- data/.rspec +3 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +63 -0
- data/LICENSE.txt +21 -0
- data/README.md +79 -0
- data/Rakefile +8 -0
- data/features/failure.feature +89 -0
- data/features/state.feature +67 -0
- data/features/step_definitions/output.rb +10 -0
- data/features/step_definitions/temporary_code_scope.rb +16 -0
- data/features/steps_definition.feature +111 -0
- data/features/support/env.rb +4 -0
- data/lib/rung.rb +18 -0
- data/lib/rung/base.rb +13 -0
- data/lib/rung/definition/steps/nested_step.rb +20 -0
- data/lib/rung/definition/steps/step.rb +30 -0
- data/lib/rung/definition/steps_definition.rb +13 -0
- data/lib/rung/definition/steps_dsl.rb +52 -0
- data/lib/rung/error.rb +3 -0
- data/lib/rung/runner/call_helper.rb +33 -0
- data/lib/rung/runner/result.rb +24 -0
- data/lib/rung/runner/run_context.rb +26 -0
- data/lib/rung/runner/run_state.rb +12 -0
- data/lib/rung/runner/runner.rb +53 -0
- data/lib/rung/version.rb +3 -0
- data/rung.gemspec +28 -0
- metadata +127 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a7cd0b72e47764f703e416e708f76644255e53df
|
4
|
+
data.tar.gz: 7887c8167710d0c089c792ca25c53a79b2fe053a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 15ad2faba325fe974e782ac1941255e0ab80b2dddf269d77892d30a0ebb4a99e67844978b5dbc5dc7ad8c3ec97cd222e2e80ca3536ea6d9e2753ba4a1ee9f8e3
|
7
|
+
data.tar.gz: bb56850efb181213e11bae971feea9f659408f668598d1994bde7be06eba32010b2cd9603eb490c5b4c5640c13976ec7318ae03404b5511029d5cda924072248
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rung (0.0.1.pre.alpha)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
backports (3.11.4)
|
10
|
+
builder (3.2.3)
|
11
|
+
coderay (1.1.2)
|
12
|
+
cucumber (3.1.2)
|
13
|
+
builder (>= 2.1.2)
|
14
|
+
cucumber-core (~> 3.2.0)
|
15
|
+
cucumber-expressions (~> 6.0.1)
|
16
|
+
cucumber-wire (~> 0.0.1)
|
17
|
+
diff-lcs (~> 1.3)
|
18
|
+
gherkin (~> 5.1.0)
|
19
|
+
multi_json (>= 1.7.5, < 2.0)
|
20
|
+
multi_test (>= 0.1.2)
|
21
|
+
cucumber-core (3.2.1)
|
22
|
+
backports (>= 3.8.0)
|
23
|
+
cucumber-tag_expressions (~> 1.1.0)
|
24
|
+
gherkin (~> 5.0)
|
25
|
+
cucumber-expressions (6.0.1)
|
26
|
+
cucumber-tag_expressions (1.1.1)
|
27
|
+
cucumber-wire (0.0.1)
|
28
|
+
diff-lcs (1.3)
|
29
|
+
gherkin (5.1.0)
|
30
|
+
method_source (0.9.2)
|
31
|
+
multi_json (1.13.1)
|
32
|
+
multi_test (0.1.2)
|
33
|
+
pry (0.12.2)
|
34
|
+
coderay (~> 1.1.0)
|
35
|
+
method_source (~> 0.9.0)
|
36
|
+
rake (10.5.0)
|
37
|
+
rspec (3.8.0)
|
38
|
+
rspec-core (~> 3.8.0)
|
39
|
+
rspec-expectations (~> 3.8.0)
|
40
|
+
rspec-mocks (~> 3.8.0)
|
41
|
+
rspec-core (3.8.0)
|
42
|
+
rspec-support (~> 3.8.0)
|
43
|
+
rspec-expectations (3.8.2)
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
45
|
+
rspec-support (~> 3.8.0)
|
46
|
+
rspec-mocks (3.8.0)
|
47
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
48
|
+
rspec-support (~> 3.8.0)
|
49
|
+
rspec-support (3.8.0)
|
50
|
+
|
51
|
+
PLATFORMS
|
52
|
+
ruby
|
53
|
+
|
54
|
+
DEPENDENCIES
|
55
|
+
bundler (~> 1.16)
|
56
|
+
cucumber (~> 3.1)
|
57
|
+
pry
|
58
|
+
rake (~> 10.0)
|
59
|
+
rspec (~> 3.0)
|
60
|
+
rung!
|
61
|
+
|
62
|
+
BUNDLED WITH
|
63
|
+
1.16.3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Jan Jedrychowski
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Rung
|
2
|
+
|
3
|
+
Rung is service object/business operation/Railway DSL, inspired by [Trailblazer Operation](http://trailblazer.to/gems/operation).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'rung'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install rung
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Example:
|
24
|
+
```ruby
|
25
|
+
class CreateOrder < Rung::Base
|
26
|
+
step do |state|
|
27
|
+
state[:order_id] = "order-#{SecureRandom.uuid }"
|
28
|
+
end
|
29
|
+
step ValidateMagazineState
|
30
|
+
step :log_start
|
31
|
+
|
32
|
+
wrap WithBenchmark do
|
33
|
+
step CreateTemporaryOrder
|
34
|
+
step :place_order
|
35
|
+
end
|
36
|
+
|
37
|
+
step :log_success
|
38
|
+
failure :log_failure
|
39
|
+
|
40
|
+
def log_start(state)
|
41
|
+
state[:logger].log("Creating order #{state[:order_id]}")
|
42
|
+
end
|
43
|
+
|
44
|
+
def log_success(state)
|
45
|
+
state[:logger].log("Order #{state[:order_id]} created successfully")
|
46
|
+
end
|
47
|
+
|
48
|
+
def log_failure(state)
|
49
|
+
state[:logger].log("Order #{state[:order_id]} not created")
|
50
|
+
end
|
51
|
+
|
52
|
+
def place_order(state)
|
53
|
+
status = OrdersRepository.create(state[:order_id])
|
54
|
+
|
55
|
+
# Step return value is important.
|
56
|
+
# If step returns falsy value then the operation is considered as a failure.
|
57
|
+
status == :success
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
result = CreateOrder.call(logger: Rails.logger)
|
62
|
+
if result.success?
|
63
|
+
print "Created order #{result[:order_id]}"
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
## Development
|
68
|
+
|
69
|
+
After checking out the repo, run `bundle` to install dependencies. Then, run `rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
70
|
+
|
71
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
Bug reports and pull requests are welcome on GitHub.
|
76
|
+
|
77
|
+
## License
|
78
|
+
|
79
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
Feature: failure
|
2
|
+
Operation call returns `Rung::Runner::Result` object that can be either a success or a failure.
|
3
|
+
Result has `success?` and `failure?` methods.
|
4
|
+
|
5
|
+
Scenario: When all steps return truthy value the result is a success
|
6
|
+
Given definition
|
7
|
+
"""ruby
|
8
|
+
class Operation < Rung::Base
|
9
|
+
step do
|
10
|
+
# do something...
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
step :second_step
|
15
|
+
|
16
|
+
def second_step
|
17
|
+
2 + 2
|
18
|
+
end
|
19
|
+
end
|
20
|
+
"""
|
21
|
+
When I run
|
22
|
+
"""
|
23
|
+
@result = Operation.new.call
|
24
|
+
"""
|
25
|
+
Then I can assure that
|
26
|
+
"""
|
27
|
+
@result.success? == true
|
28
|
+
"""
|
29
|
+
And I can assure that
|
30
|
+
"""
|
31
|
+
@result.failure? == false
|
32
|
+
"""
|
33
|
+
|
34
|
+
Scenario: When at least one step returns a falsy value then the result is a failure
|
35
|
+
Given definition
|
36
|
+
"""ruby
|
37
|
+
class Operation < Rung::Base
|
38
|
+
step do
|
39
|
+
# do something...
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
step :second_step
|
44
|
+
|
45
|
+
def second_step
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
"""
|
50
|
+
When I run
|
51
|
+
"""
|
52
|
+
@result = Operation.new.call
|
53
|
+
"""
|
54
|
+
Then I can assure that
|
55
|
+
"""
|
56
|
+
@result.success? == false
|
57
|
+
"""
|
58
|
+
And I can assure that
|
59
|
+
"""
|
60
|
+
@result.failure? == true
|
61
|
+
"""
|
62
|
+
|
63
|
+
Scenario: When a step fails then the next steps are not executed
|
64
|
+
Given definition
|
65
|
+
"""ruby
|
66
|
+
class Operation < Rung::Base
|
67
|
+
step do
|
68
|
+
print_to_output "Hello"
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
step do
|
73
|
+
# something went wrong, retuning false
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
step do
|
78
|
+
print_to_output "World"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
"""
|
82
|
+
When I run
|
83
|
+
"""
|
84
|
+
Operation.new.call
|
85
|
+
"""
|
86
|
+
Then I see output
|
87
|
+
"""
|
88
|
+
Hello
|
89
|
+
"""
|
@@ -0,0 +1,67 @@
|
|
1
|
+
Feature: state
|
2
|
+
|
3
|
+
Scenario: State is shared across step executions
|
4
|
+
Given definition
|
5
|
+
"""ruby
|
6
|
+
class Operation < Rung::Base
|
7
|
+
step do |state|
|
8
|
+
state[:what] = "World!"
|
9
|
+
end
|
10
|
+
|
11
|
+
step do
|
12
|
+
print_to_output "Hello "
|
13
|
+
end
|
14
|
+
|
15
|
+
step do |state|
|
16
|
+
print_to_output state[:what]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
"""
|
20
|
+
When I run
|
21
|
+
"""
|
22
|
+
Operation.new.call
|
23
|
+
"""
|
24
|
+
Then I see output
|
25
|
+
"""
|
26
|
+
Hello World!
|
27
|
+
"""
|
28
|
+
|
29
|
+
Scenario: State is available in the result object
|
30
|
+
Given definition
|
31
|
+
"""ruby
|
32
|
+
class Operation < Rung::Base
|
33
|
+
step do |state|
|
34
|
+
state[:output_text] = "Hello "
|
35
|
+
end
|
36
|
+
|
37
|
+
step do |state|
|
38
|
+
state[:output_text] << "World!"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
"""
|
42
|
+
When I run
|
43
|
+
"""
|
44
|
+
@result = Operation.new.call
|
45
|
+
"""
|
46
|
+
Then I can assure that
|
47
|
+
"""
|
48
|
+
@result[:output_text] == "Hello World!"
|
49
|
+
"""
|
50
|
+
|
51
|
+
Scenario: Initial state can be passed to call method
|
52
|
+
Given definition
|
53
|
+
"""ruby
|
54
|
+
class Operation < Rung::Base
|
55
|
+
step do |state|
|
56
|
+
state[:output_text] << "World!"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
"""
|
60
|
+
When I run
|
61
|
+
"""
|
62
|
+
@result = Operation.new.call(output_text: "Hello ")
|
63
|
+
"""
|
64
|
+
Then I can assure that
|
65
|
+
"""
|
66
|
+
@result[:output_text] == "Hello World!"
|
67
|
+
"""
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class TemporaryScope
|
2
|
+
end
|
3
|
+
|
4
|
+
Given("definition") do |content|
|
5
|
+
@temporary_scope ||= TemporaryScope.new
|
6
|
+
|
7
|
+
@temporary_scope.instance_eval(content)
|
8
|
+
end
|
9
|
+
|
10
|
+
When("I run") do |content|
|
11
|
+
@temporary_scope.instance_eval(content)
|
12
|
+
end
|
13
|
+
|
14
|
+
Then("I can assure that") do |content|
|
15
|
+
expect(@temporary_scope.instance_eval(content)).to eq true
|
16
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
Feature: steps_definition
|
2
|
+
There are multiple ways of defining steps.
|
3
|
+
Steps definition order is important as they are always executed in order.
|
4
|
+
|
5
|
+
Scenario: Steps can be defined as a Ruby block
|
6
|
+
Given definition
|
7
|
+
"""ruby
|
8
|
+
class Operation < Rung::Base
|
9
|
+
step do |state|
|
10
|
+
state[:what] = "World"
|
11
|
+
end
|
12
|
+
|
13
|
+
step do
|
14
|
+
print_to_output "Hello "
|
15
|
+
end
|
16
|
+
|
17
|
+
step do |state|
|
18
|
+
print_to_output state[:what]
|
19
|
+
end
|
20
|
+
|
21
|
+
step do
|
22
|
+
print_to_output "!"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
"""
|
26
|
+
When I run
|
27
|
+
"""
|
28
|
+
Operation.new.call
|
29
|
+
"""
|
30
|
+
Then I see output
|
31
|
+
"""
|
32
|
+
Hello World!
|
33
|
+
"""
|
34
|
+
|
35
|
+
Scenario: Steps can be defined as methods
|
36
|
+
Given definition
|
37
|
+
"""ruby
|
38
|
+
class Operation < Rung::Base
|
39
|
+
step :set_what_state
|
40
|
+
step :print_hello
|
41
|
+
step "print_what"
|
42
|
+
step :print_bang
|
43
|
+
|
44
|
+
def set_what_state(state)
|
45
|
+
state[:what] = "World"
|
46
|
+
end
|
47
|
+
|
48
|
+
def print_hello
|
49
|
+
print_to_output "Hello "
|
50
|
+
end
|
51
|
+
|
52
|
+
def print_what(state)
|
53
|
+
print_to_output state[:what]
|
54
|
+
end
|
55
|
+
|
56
|
+
def print_bang
|
57
|
+
print_to_output "!"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
"""
|
61
|
+
When I run
|
62
|
+
"""
|
63
|
+
Operation.new.call
|
64
|
+
"""
|
65
|
+
Then I see output
|
66
|
+
"""
|
67
|
+
Hello World!
|
68
|
+
"""
|
69
|
+
|
70
|
+
Scenario: Steps can be defined as any objects with call method
|
71
|
+
Given definition
|
72
|
+
"""ruby
|
73
|
+
class SetWhatState
|
74
|
+
def initialize(what)
|
75
|
+
@what = what
|
76
|
+
end
|
77
|
+
|
78
|
+
def call(state)
|
79
|
+
state[:what] = @what
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class PrintHello
|
84
|
+
def self.call
|
85
|
+
print_to_output "Hello "
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class PrintWhat
|
90
|
+
def self.call(state)
|
91
|
+
print_to_output state[:what]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
PrintBang = -> { print_to_output "!" }
|
96
|
+
|
97
|
+
class Operation < Rung::Base
|
98
|
+
step SetWhatState.new("World")
|
99
|
+
step PrintHello
|
100
|
+
step PrintWhat
|
101
|
+
step PrintBang
|
102
|
+
end
|
103
|
+
"""
|
104
|
+
When I run
|
105
|
+
"""
|
106
|
+
Operation.new.call
|
107
|
+
"""
|
108
|
+
Then I see output
|
109
|
+
"""
|
110
|
+
Hello World!
|
111
|
+
"""
|
data/lib/rung.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'rung/version'
|
4
|
+
require 'rung/error'
|
5
|
+
|
6
|
+
require 'rung/definition/steps/step'
|
7
|
+
require 'rung/definition/steps/nested_step'
|
8
|
+
|
9
|
+
require 'rung/definition/steps_definition'
|
10
|
+
require 'rung/definition/steps_dsl'
|
11
|
+
|
12
|
+
require 'rung/runner/result'
|
13
|
+
require 'rung/runner/run_context'
|
14
|
+
require 'rung/runner/run_state'
|
15
|
+
require 'rung/runner/call_helper'
|
16
|
+
require 'rung/runner/runner'
|
17
|
+
|
18
|
+
require 'rung/base'
|
data/lib/rung/base.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Rung
|
2
|
+
class Base
|
3
|
+
extend Definition::StepsDSL
|
4
|
+
|
5
|
+
def self.call(initial_state = {})
|
6
|
+
new.call(initial_state)
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(initial_state = {})
|
10
|
+
Runner::Runner.new(self.class.steps_definition, initial_state, self).call
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rung
|
2
|
+
module Definition
|
3
|
+
class NestedStep
|
4
|
+
def initialize(operation, nested_steps)
|
5
|
+
@operation = operation
|
6
|
+
@nested_steps = nested_steps
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :operation, :nested_steps
|
10
|
+
|
11
|
+
def run?(_success)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def nested?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Rung
|
2
|
+
module Definition
|
3
|
+
class Step
|
4
|
+
def initialize(operation, from_block: false, run_on: :success)
|
5
|
+
@operation = operation
|
6
|
+
@from_block = from_block if from_block
|
7
|
+
@run_on = run_on
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :operation, :from_block
|
11
|
+
|
12
|
+
def run?(success)
|
13
|
+
case @run_on
|
14
|
+
when :success
|
15
|
+
success
|
16
|
+
when :failure
|
17
|
+
!success
|
18
|
+
when :any
|
19
|
+
true
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def nested?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Rung
|
2
|
+
module Definition
|
3
|
+
module StepsDSL
|
4
|
+
def steps_definition
|
5
|
+
@steps_definition ||= StepsDefinition.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def step(reference = nil, &block)
|
9
|
+
add_step(reference, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def failure(reference = nil, &block)
|
13
|
+
add_step(reference, run_on: :failure, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def wrap(wrapper, &block)
|
17
|
+
nested_steps = calculate_block_nested_steps(&block)
|
18
|
+
add_nested_step wrapper, nested_steps
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def add_step(reference, options = {}, &block)
|
24
|
+
step = if block
|
25
|
+
Step.new(block, *options, from_block: true)
|
26
|
+
else
|
27
|
+
Step.new(reference, options)
|
28
|
+
end
|
29
|
+
steps_definition.push(step)
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_nested_step(operation, nested_steps)
|
33
|
+
steps_definition.push(NestedStep.new(operation, nested_steps))
|
34
|
+
end
|
35
|
+
|
36
|
+
def calculate_block_nested_steps(&block)
|
37
|
+
with_new_steps_definition do
|
38
|
+
instance_exec(&block)
|
39
|
+
steps_definition
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def with_new_steps_definition
|
44
|
+
old_steps_definition = @steps_definition
|
45
|
+
@steps_definition = StepsDefinition.new
|
46
|
+
yield
|
47
|
+
ensure
|
48
|
+
@steps_definition = old_steps_definition
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/rung/error.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rung
|
2
|
+
module Runner
|
3
|
+
module CallHelper
|
4
|
+
class << self
|
5
|
+
def call(operation, state, operation_instance, from_block = false, &block)
|
6
|
+
raise "Can't pass block when from_block is enabled" if block && from_block
|
7
|
+
runnable = to_runnable(operation, operation_instance)
|
8
|
+
|
9
|
+
if from_block
|
10
|
+
runnable.arity.zero? ? operation_instance.instance_exec(&runnable) : operation_instance.instance_exec(state, &runnable)
|
11
|
+
else
|
12
|
+
runnable.arity.zero? ? runnable.call(&block) : runnable.call(state, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def to_runnable(operation, operation_instance)
|
19
|
+
case operation
|
20
|
+
when Symbol, String
|
21
|
+
operation_instance.method(operation)
|
22
|
+
when Proc
|
23
|
+
operation
|
24
|
+
else
|
25
|
+
operation.method(:call)
|
26
|
+
end
|
27
|
+
rescue NameError
|
28
|
+
operation
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rung
|
2
|
+
module Runner
|
3
|
+
class Result
|
4
|
+
def initialize(success, state)
|
5
|
+
@success = success
|
6
|
+
@state = state
|
7
|
+
end
|
8
|
+
|
9
|
+
def success?
|
10
|
+
!!@success
|
11
|
+
end
|
12
|
+
|
13
|
+
def failure?
|
14
|
+
!success?
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
state[key]
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :state
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Rung
|
2
|
+
module Runner
|
3
|
+
class RunContext
|
4
|
+
def initialize(steps_definition:, operation_instance:, state:)
|
5
|
+
@steps_definition = steps_definition
|
6
|
+
@operation_instance = operation_instance
|
7
|
+
@state = state
|
8
|
+
@failed = false
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :steps_definition, :operation_instance, :state
|
12
|
+
|
13
|
+
def fail!
|
14
|
+
@failed = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def failed?
|
18
|
+
@failed
|
19
|
+
end
|
20
|
+
|
21
|
+
def success?
|
22
|
+
!failed?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Rung
|
2
|
+
module Runner
|
3
|
+
class Runner
|
4
|
+
def initialize(steps_definition, initial_state, operation_instance)
|
5
|
+
@context = RunContext.new(
|
6
|
+
steps_definition: steps_definition,
|
7
|
+
operation_instance: operation_instance,
|
8
|
+
state: RunState.new(initial_state)
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
extend Forwardable
|
13
|
+
def_delegators :@context,
|
14
|
+
:steps_definition, :operation_instance, :state, :failed?, :success?, :fail!
|
15
|
+
|
16
|
+
def call
|
17
|
+
run_success = iterate(steps_definition)
|
18
|
+
|
19
|
+
Result.new(run_success, state)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def iterate(steps_definition)
|
25
|
+
steps_definition.each(&method(:run_step))
|
26
|
+
|
27
|
+
success?
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_step(step)
|
31
|
+
return unless step.run?(success?)
|
32
|
+
|
33
|
+
step_success = call_step(step)
|
34
|
+
|
35
|
+
fail! unless step_success
|
36
|
+
end
|
37
|
+
|
38
|
+
def call_step(step)
|
39
|
+
step.nested? ? call_nested_step(step) : call_simple_step(step)
|
40
|
+
end
|
41
|
+
|
42
|
+
def call_nested_step(nested)
|
43
|
+
CallHelper.call(nested.operation, state, operation_instance) do
|
44
|
+
iterate(nested.nested_steps)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def call_simple_step(step)
|
49
|
+
CallHelper.call(step.operation, state, operation_instance, step.from_block)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/rung/version.rb
ADDED
data/rung.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "rung/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rung"
|
7
|
+
spec.version = Rung::VERSION
|
8
|
+
spec.authors = ["Jan Jędrychowski"]
|
9
|
+
spec.email = ["jan@jedrychowski.org"]
|
10
|
+
|
11
|
+
spec.summary = %q{Business operations DSL}
|
12
|
+
spec.description = %q{Service object/business operation/Railway DSL, inspired by Trailblazer Operation}
|
13
|
+
spec.homepage = "https://github.com/gogiel/rung"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|bin)/}) }
|
21
|
+
end
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
27
|
+
spec.add_development_dependency "cucumber", "~> 3.1"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rung
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.pre.alpha
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jan Jędrychowski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-01-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: cucumber
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.1'
|
69
|
+
description: Service object/business operation/Railway DSL, inspired by Trailblazer
|
70
|
+
Operation
|
71
|
+
email:
|
72
|
+
- jan@jedrychowski.org
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".rspec"
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- features/failure.feature
|
84
|
+
- features/state.feature
|
85
|
+
- features/step_definitions/output.rb
|
86
|
+
- features/step_definitions/temporary_code_scope.rb
|
87
|
+
- features/steps_definition.feature
|
88
|
+
- features/support/env.rb
|
89
|
+
- lib/rung.rb
|
90
|
+
- lib/rung/base.rb
|
91
|
+
- lib/rung/definition/steps/nested_step.rb
|
92
|
+
- lib/rung/definition/steps/step.rb
|
93
|
+
- lib/rung/definition/steps_definition.rb
|
94
|
+
- lib/rung/definition/steps_dsl.rb
|
95
|
+
- lib/rung/error.rb
|
96
|
+
- lib/rung/runner/call_helper.rb
|
97
|
+
- lib/rung/runner/result.rb
|
98
|
+
- lib/rung/runner/run_context.rb
|
99
|
+
- lib/rung/runner/run_state.rb
|
100
|
+
- lib/rung/runner/runner.rb
|
101
|
+
- lib/rung/version.rb
|
102
|
+
- rung.gemspec
|
103
|
+
homepage: https://github.com/gogiel/rung
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata: {}
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">"
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 1.3.1
|
121
|
+
requirements: []
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 2.5.2.1
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
126
|
+
summary: Business operations DSL
|
127
|
+
test_files: []
|