tzu 0.1.0.0 → 0.1.1.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/README.md +144 -10
- data/lib/tzu/errors.rb +4 -0
- data/lib/tzu/hooks.rb +4 -4
- data/lib/tzu/run_methods.rb +2 -2
- data/lib/tzu/sequence.rb +19 -13
- data/lib/tzu/step.rb +38 -8
- data/lib/tzu.rb +1 -0
- data/spec/sequence_spec.rb +45 -19
- data/spec/step_spec.rb +32 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b65373fa789405d5d165a29c71bd15b3a227450b
|
4
|
+
data.tar.gz: e7a9845bc66eba286135a9e7cbb64b9c197fa409
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9a239244309bd5eae81848753bbdcdad5b22aac74b070ff73cb4ea843be47c1715a19758e06bcf6ed0025066423c2f6cace651b1f84f4f8b02888e767a09044
|
7
|
+
data.tar.gz: 14b6723526bfa3dbe24a36d5dc65caa122cbc5f2e12eb2c7891aacedb6d89542736809ecca93044da744e2296e8ff190995695b05a49d042e15e4f883756815d
|
data/README.md
CHANGED
@@ -1,5 +1,36 @@
|
|
1
1
|
# Tzu
|
2
2
|
|
3
|
+
Tzu provides a simple interface for writing classes that encapsulate a single command.
|
4
|
+
|
5
|
+
**Commands should:**
|
6
|
+
|
7
|
+
- Do exactly one thing (Single Responsibility Priciple)
|
8
|
+
- Be self-documenting
|
9
|
+
- Be testable
|
10
|
+
- Be easy to mock and stub
|
11
|
+
|
12
|
+
**Benefits**
|
13
|
+
|
14
|
+
- File and class names say what your code *actually does*, making onboarding and debugging a much simpler process.
|
15
|
+
- Minimize the instances of persistence logic throughout the application
|
16
|
+
- The Rails 'where do I put...?' question is solved. Models, Controllers, Workers and even Rake Tasks become slim.
|
17
|
+
- Maintain all of the benefits of Object Oriented programming while executing a procedural action, or Sequence of procedural actions.
|
18
|
+
|
19
|
+
**Documentation**
|
20
|
+
|
21
|
+
- [Usage](#usage)
|
22
|
+
- [Validation](#validation)
|
23
|
+
- [Passing Blocks](#passing-blocks)
|
24
|
+
- [Hooks](#hooks)
|
25
|
+
- [Request Objects](#request-objects)
|
26
|
+
|
27
|
+
**Sequences**
|
28
|
+
- [Configure](#configure)
|
29
|
+
- [Execute](#execute)
|
30
|
+
- [Integrating Non Tzu Classes](#integrating-non-tzu-classes)
|
31
|
+
- [Hooks for Sequences](#hooks-for-sequences)
|
32
|
+
- [Mocking and Stubbing](#mocking-and-stubbing)
|
33
|
+
|
3
34
|
## Usage
|
4
35
|
|
5
36
|
Tzu commands must include Tzu and implement a `#call` method.
|
@@ -79,7 +110,11 @@ outcome = MyRescueCommand.run!(params_that_cause_error)
|
|
79
110
|
|
80
111
|
Note that if you pass a string to `invalid!`, it will coerce the result into a hash of the form:
|
81
112
|
|
82
|
-
```
|
113
|
+
```ruby
|
114
|
+
# Invoking:
|
115
|
+
invalid!('Error String')
|
116
|
+
|
117
|
+
# Translates to:
|
83
118
|
{ errors: 'Error String' }
|
84
119
|
```
|
85
120
|
|
@@ -149,9 +184,7 @@ MyCommand.run(message: 'Hello!')
|
|
149
184
|
#=> End Around 1
|
150
185
|
```
|
151
186
|
|
152
|
-
|
153
|
-
|
154
|
-
## Request objects
|
187
|
+
## Request Objects
|
155
188
|
|
156
189
|
You can define a request object for your command using the `#request_object` method.
|
157
190
|
|
@@ -196,6 +229,7 @@ Virtus.model validates the types of your inputs, and also makes them available v
|
|
196
229
|
class MyRequestObject
|
197
230
|
include Virtus.model
|
198
231
|
include ActiveModel::Validations
|
232
|
+
|
199
233
|
validates :name, :age, presence: :true
|
200
234
|
|
201
235
|
attribute :name, String
|
@@ -225,7 +259,9 @@ outcome.type? #=> :validation
|
|
225
259
|
outcome.result #=> {:age=>["can't be blank"]}
|
226
260
|
```
|
227
261
|
|
228
|
-
#
|
262
|
+
# Execute Commands in Sequence
|
263
|
+
|
264
|
+
## Configure
|
229
265
|
|
230
266
|
Tzu provides a declarative way of encapsulating sequential command execution.
|
231
267
|
|
@@ -249,7 +285,7 @@ class MakeMeSoundImportant
|
|
249
285
|
end
|
250
286
|
```
|
251
287
|
|
252
|
-
|
288
|
+
Tzu::Sequence provides a DSL for executing them in sequence:
|
253
289
|
|
254
290
|
```ruby
|
255
291
|
class ProclaimMyImportance
|
@@ -276,7 +312,7 @@ Each command to be executed is defined as the first argument of `step`.
|
|
276
312
|
The `receives` method inside the `step` block allows you to mutate the parameters being passed into the command.
|
277
313
|
It is passed both the original parameters and a hash containing the results of prior commands.
|
278
314
|
|
279
|
-
By default, the keys of the `prior_results` hash are underscored/symbolized command names.
|
315
|
+
By default, the keys of the `prior_results` hash are demodulized/underscored/symbolized command names.
|
280
316
|
You can define your own keys using the `as` method.
|
281
317
|
|
282
318
|
```ruby
|
@@ -288,9 +324,15 @@ step SayMyName do
|
|
288
324
|
end
|
289
325
|
```
|
290
326
|
|
291
|
-
|
327
|
+
If you don't need to mutate the parameters for the command, simply omit `receives`.
|
328
|
+
|
329
|
+
```ruby
|
330
|
+
step SayMyName
|
331
|
+
```
|
292
332
|
|
293
|
-
|
333
|
+
## Execute
|
334
|
+
|
335
|
+
By default, Sequences return the result of the final command.
|
294
336
|
|
295
337
|
```ruby
|
296
338
|
outcome = ProclaimMyImportance.run(name: 'Jessica', country: 'Azerbaijan')
|
@@ -363,7 +405,95 @@ outcome.result
|
|
363
405
|
#=> { name: 'Jessica', original_message: 'Hello, Jessica', message: 'BULLETIN: Hello, Jessica! You are the most important citizen of Azerbaijan!' }
|
364
406
|
```
|
365
407
|
|
366
|
-
|
408
|
+
## Integrating Non Tzu Classes
|
409
|
+
|
410
|
+
Sometimes there is a need to combine non-Tzu classes with Tzu classes in a sequence.
|
411
|
+
|
412
|
+
As an example, let's say I wanted to query a record, update it, and pass the updated record to a Tzu command.
|
413
|
+
To do this, I'll use the [Get](https://github.com/onfido/get) and [Tradesman](https://github.com/onfido/tradesman/) libraries.
|
414
|
+
|
415
|
+
When invoked on its own, Get looks like this:
|
416
|
+
```ruby
|
417
|
+
Get::UserByName.run(name)
|
418
|
+
```
|
419
|
+
|
420
|
+
Tradesman Update looks like this:
|
421
|
+
```ruby
|
422
|
+
Tradesman::UpdateUser.go(user_id, update_params)
|
423
|
+
```
|
424
|
+
|
425
|
+
The integration of Get into `Tzu::Sequence` is easy, as it only expects one parameter, and it's invoked with `#run`.
|
426
|
+
Tradesman is more complicated; it expects two parameters - a User ID and a hash to update that record with - and it's invoked with `#go`.
|
427
|
+
|
428
|
+
Tradesman offers the `invoke_with` and `receives_many` arguments to deal with these differences.
|
429
|
+
|
430
|
+
`invoke_with` is self-explanatory, and defaults to `#run`.
|
431
|
+
|
432
|
+
The `receives_many` block must return an array, which will be passed as a splat to the `invoke_with` method.
|
433
|
+
```ruby
|
434
|
+
class NonTzuSequence
|
435
|
+
include Tzu::Sequence
|
436
|
+
|
437
|
+
step Get::UserByName do
|
438
|
+
receives do |params|
|
439
|
+
params[:name]
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
step Tradesman::UpdateUser do
|
444
|
+
invoke_with :go
|
445
|
+
|
446
|
+
receives_many do |params, prior_results|
|
447
|
+
[
|
448
|
+
prior_results[:user_by_name].id,
|
449
|
+
params[:update_params]
|
450
|
+
]
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
step SayMyName do
|
455
|
+
receives do |params, prior_results|
|
456
|
+
prior_results[:update_user].name
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
outcome = NonTzuSequence.run(name: 'Blake', update_params: { name: 'Morgan' })
|
462
|
+
outcome.result #=> 'Hello, Morgan'
|
463
|
+
```
|
464
|
+
|
465
|
+
You can pass multiple parameters to `Tzu::Sequence` instead of a parameters hash, just make sure you add the correct amount of arguments to your `receives` and `receives_many` blocks.
|
466
|
+
|
467
|
+
```ruby
|
468
|
+
class NonTzuSequence
|
469
|
+
include Tzu::Sequence
|
470
|
+
|
471
|
+
step Get::UserByName do
|
472
|
+
receives do |name, update_params|
|
473
|
+
name
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
step Tradesman::UpdateUser do
|
478
|
+
invoke_with :go
|
479
|
+
|
480
|
+
receives_many do |name, update_params, prior_results|
|
481
|
+
[prior_results[:user_by_name].id, update_params]
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
step SayMyName do
|
486
|
+
receives do |name, update_params, prior_results|
|
487
|
+
prior_results[:update_user].name
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
outcome = NonTzuSequence.run('Blake', { name: 'Morgan' })
|
493
|
+
outcome.result #=> 'Hello, Morgan'
|
494
|
+
```
|
495
|
+
|
496
|
+
## Hooks for Sequences
|
367
497
|
|
368
498
|
Tzu sequences have the same `before`, `after`, and `around` hooks available in Tzu commands.
|
369
499
|
This is particularly useful for wrapping multiple commands in a transaction.
|
@@ -394,3 +524,7 @@ class ProclaimMyImportance
|
|
394
524
|
end
|
395
525
|
end
|
396
526
|
```
|
527
|
+
|
528
|
+
## Mocking and Stubbing
|
529
|
+
|
530
|
+
Tzu has a specialized (and well-documented) gem for mocking/stubbing, [TzuMock](https://github.com/onfido/tzu_mock).
|
data/lib/tzu/errors.rb
ADDED
data/lib/tzu/hooks.rb
CHANGED
@@ -37,12 +37,12 @@ module Tzu
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def with_hooks(params, &block)
|
40
|
+
def with_hooks(*params, &block)
|
41
41
|
result = nil
|
42
42
|
run_around_hooks do
|
43
|
-
run_before_hooks(params)
|
44
|
-
result = yield(params)
|
45
|
-
run_after_hooks(params)
|
43
|
+
run_before_hooks(*params)
|
44
|
+
result = yield(*params)
|
45
|
+
run_after_hooks(*params)
|
46
46
|
end
|
47
47
|
result
|
48
48
|
end
|
data/lib/tzu/run_methods.rb
CHANGED
data/lib/tzu/sequence.rb
CHANGED
@@ -7,13 +7,8 @@ module Tzu
|
|
7
7
|
class << self
|
8
8
|
attr_reader :steps, :result_block
|
9
9
|
|
10
|
-
def run(params)
|
11
|
-
new(params).run
|
12
|
-
end
|
13
|
-
|
14
|
-
def method_missing(method, *args, &block)
|
15
|
-
return add_step(args.first, &block) if method == :step
|
16
|
-
super
|
10
|
+
def run(*params)
|
11
|
+
new(*params).run
|
17
12
|
end
|
18
13
|
|
19
14
|
def type
|
@@ -25,19 +20,20 @@ module Tzu
|
|
25
20
|
@type = type
|
26
21
|
end
|
27
22
|
|
28
|
-
def
|
23
|
+
def step(klass, &block)
|
29
24
|
@steps = [] unless @steps
|
30
25
|
|
31
26
|
step = Step.new(klass)
|
32
|
-
step.instance_eval(&block)
|
27
|
+
step.instance_eval(&block) if block
|
33
28
|
|
34
29
|
@steps << step
|
35
30
|
end
|
36
31
|
end
|
37
32
|
|
38
|
-
def initialize(params)
|
33
|
+
def initialize(*params)
|
39
34
|
@params = params
|
40
35
|
@last_outcome = nil
|
36
|
+
@prior_results = {}
|
41
37
|
end
|
42
38
|
|
43
39
|
def run
|
@@ -50,15 +46,25 @@ module Tzu
|
|
50
46
|
def sequence_results
|
51
47
|
with_hooks(@params) do |params|
|
52
48
|
self.class.steps.reduce({}) do |prior_results, step|
|
53
|
-
@last_outcome = step.run(params, prior_results)
|
54
|
-
break if
|
55
|
-
|
49
|
+
@last_outcome = step.run(*params, prior_results)
|
50
|
+
break if last_outcome_is_failure?
|
51
|
+
merge_last_outcome_into_prior_results(step, prior_results)
|
56
52
|
end
|
57
53
|
end
|
58
54
|
end
|
59
55
|
|
60
56
|
private
|
61
57
|
|
58
|
+
def last_outcome_is_failure?
|
59
|
+
return true if (@last_outcome.respond_to?(:failure?) && @last_outcome.failure?)
|
60
|
+
false
|
61
|
+
end
|
62
|
+
|
63
|
+
def merge_last_outcome_into_prior_results(step, prior_results)
|
64
|
+
result = @last_outcome.respond_to?(:result) ? @last_outcome.result : @last_outcome
|
65
|
+
prior_results.merge(step.name => result)
|
66
|
+
end
|
67
|
+
|
62
68
|
def mutated_result(results)
|
63
69
|
Outcome.new(true, instance_exec(@params, results, &self.class.result_block))
|
64
70
|
end
|
data/lib/tzu/step.rb
CHANGED
@@ -1,34 +1,64 @@
|
|
1
1
|
module Tzu
|
2
2
|
class Step
|
3
|
+
DOUBLE_MUTATOR = 'You cannot define both receives and receives_many'
|
4
|
+
|
3
5
|
String.send(:include, ::Tzu::CoreExtensions::String)
|
4
|
-
attr_reader :klass, :
|
6
|
+
attr_reader :klass, :single_mutator, :splat_mutator
|
5
7
|
|
6
8
|
def initialize(klass)
|
7
9
|
@klass = klass
|
10
|
+
@invoke_method = :run
|
8
11
|
end
|
9
12
|
|
10
|
-
def run(params, prior_results)
|
11
|
-
|
12
|
-
@klass.
|
13
|
+
def run(*params, prior_results)
|
14
|
+
# Forward parameters as splat if no mutators are defined
|
15
|
+
return @klass.send(@invoke_method, *params) if mutator.nil?
|
16
|
+
|
17
|
+
command_params = process(*params, prior_results)
|
18
|
+
|
19
|
+
return @klass.send(@invoke_method, command_params) unless splat?
|
20
|
+
@klass.send(@invoke_method, *command_params)
|
13
21
|
end
|
14
22
|
|
15
23
|
def name
|
16
24
|
return @name if @name && @name.is_a?(Symbol)
|
17
|
-
@klass.to_s.symbolize
|
25
|
+
@klass.to_s.split('::').last.symbolize
|
18
26
|
end
|
19
27
|
|
20
28
|
def receives(&block)
|
21
|
-
|
29
|
+
double_mutator_error if splat?
|
30
|
+
@single_mutator = block
|
31
|
+
end
|
32
|
+
|
33
|
+
def receives_many(&block)
|
34
|
+
double_mutator_error if @single_mutator.present?
|
35
|
+
@splat_mutator = block
|
22
36
|
end
|
23
37
|
|
24
38
|
def as(name)
|
25
39
|
@name = name
|
26
40
|
end
|
27
41
|
|
42
|
+
def invoke_with(method)
|
43
|
+
@invoke_method = method
|
44
|
+
end
|
45
|
+
|
28
46
|
private
|
29
47
|
|
30
|
-
def
|
31
|
-
|
48
|
+
def double_mutator_error
|
49
|
+
raise Tzu::InvalidSequence.new(DOUBLE_MUTATOR)
|
50
|
+
end
|
51
|
+
|
52
|
+
def mutator
|
53
|
+
@single_mutator || @splat_mutator
|
54
|
+
end
|
55
|
+
|
56
|
+
def splat?
|
57
|
+
@splat_mutator.present?
|
58
|
+
end
|
59
|
+
|
60
|
+
def process(*params, prior_results)
|
61
|
+
instance_exec(*params, prior_results, &mutator)
|
32
62
|
end
|
33
63
|
end
|
34
64
|
end
|
data/lib/tzu.rb
CHANGED
data/spec/sequence_spec.rb
CHANGED
@@ -16,7 +16,7 @@ class MakeMeSoundImportant
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
class
|
19
|
+
class ThrowInvalidError
|
20
20
|
include Tzu
|
21
21
|
|
22
22
|
def call(params)
|
@@ -24,6 +24,14 @@ class InvalidCommand
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
class ConstructGreeting
|
28
|
+
class << self
|
29
|
+
def go(greeting, name)
|
30
|
+
"#{greeting}, #{name}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
27
35
|
class MultiStepSimple
|
28
36
|
include Tzu::Sequence
|
29
37
|
|
@@ -43,14 +51,33 @@ class MultiStepSimple
|
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
54
|
+
class MultiStepNonTzu
|
55
|
+
include Tzu::Sequence
|
56
|
+
|
57
|
+
step ConstructGreeting do
|
58
|
+
as :say_my_name
|
59
|
+
invoke_with :go
|
60
|
+
|
61
|
+
receives_many do |greeting, name, country|
|
62
|
+
[greeting, name]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
step MakeMeSoundImportant do
|
67
|
+
receives do |greeting, name, country, prior_results|
|
68
|
+
{
|
69
|
+
boring_message: prior_results[:say_my_name],
|
70
|
+
country: country
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
46
76
|
class MultiStepComplex
|
47
77
|
include Tzu::Sequence
|
48
78
|
|
49
79
|
step SayMyName do
|
50
80
|
as :first_command
|
51
|
-
receives do |params|
|
52
|
-
{ name: params[:name] }
|
53
|
-
end
|
54
81
|
end
|
55
82
|
|
56
83
|
step MakeMeSoundImportant do
|
@@ -71,9 +98,6 @@ class MultiStepProcessResults
|
|
71
98
|
|
72
99
|
step SayMyName do
|
73
100
|
as :first_command
|
74
|
-
receives do |params|
|
75
|
-
{ name: params[:name] }
|
76
|
-
end
|
77
101
|
end
|
78
102
|
|
79
103
|
step MakeMeSoundImportant do
|
@@ -97,13 +121,9 @@ end
|
|
97
121
|
class MultiStepInvalid
|
98
122
|
include Tzu::Sequence
|
99
123
|
|
100
|
-
step SayMyName
|
101
|
-
receives do |params|
|
102
|
-
{ name: params[:name] }
|
103
|
-
end
|
104
|
-
end
|
124
|
+
step SayMyName
|
105
125
|
|
106
|
-
step
|
126
|
+
step ThrowInvalidError do
|
107
127
|
receives do |params, prior_results|
|
108
128
|
{ answer: "#{params[:name]}!!! #{prior_results[:say_my_name]}" }
|
109
129
|
end
|
@@ -128,16 +148,16 @@ describe Tzu::Sequence do
|
|
128
148
|
steps.each { |step| expect(step.is_a? Tzu::Step).to be true }
|
129
149
|
end
|
130
150
|
|
131
|
-
it 'passes the appropriate klass, name, and
|
151
|
+
it 'passes the appropriate klass, name, and param_mutators to each step' do
|
132
152
|
say_my_name = steps.first
|
133
153
|
expect(say_my_name.klass).to eq SayMyName
|
134
154
|
expect(say_my_name.name).to eq :say_my_name
|
135
|
-
expect(say_my_name.
|
155
|
+
expect(say_my_name.single_mutator.is_a? Proc).to be true
|
136
156
|
|
137
157
|
make_me_sound_important = steps.last
|
138
158
|
expect(make_me_sound_important.klass).to eq MakeMeSoundImportant
|
139
159
|
expect(make_me_sound_important.name).to eq :make_me_sound_important
|
140
|
-
expect(make_me_sound_important.
|
160
|
+
expect(make_me_sound_important.single_mutator.is_a? Proc).to be true
|
141
161
|
end
|
142
162
|
end
|
143
163
|
|
@@ -148,16 +168,15 @@ describe Tzu::Sequence do
|
|
148
168
|
steps.each { |step| expect(step.is_a? Tzu::Step).to be true }
|
149
169
|
end
|
150
170
|
|
151
|
-
it 'passes the appropriate klass, name, and
|
171
|
+
it 'passes the appropriate klass, name, and param_mutators to each step' do
|
152
172
|
say_my_name = steps.first
|
153
173
|
expect(say_my_name.klass).to eq SayMyName
|
154
174
|
expect(say_my_name.name).to eq :first_command
|
155
|
-
expect(say_my_name.param_mutator.is_a? Proc).to be true
|
156
175
|
|
157
176
|
make_me_sound_important = steps.last
|
158
177
|
expect(make_me_sound_important.klass).to eq MakeMeSoundImportant
|
159
178
|
expect(make_me_sound_important.name).to eq :final_command
|
160
|
-
expect(make_me_sound_important.
|
179
|
+
expect(make_me_sound_important.single_mutator.is_a? Proc).to be true
|
161
180
|
end
|
162
181
|
end
|
163
182
|
end
|
@@ -177,6 +196,13 @@ describe Tzu::Sequence do
|
|
177
196
|
end
|
178
197
|
end
|
179
198
|
|
199
|
+
context MultiStepNonTzu do
|
200
|
+
it 'returns the outcome of the last command' do
|
201
|
+
outcome = MultiStepNonTzu.run('Greetings', 'Christopher', 'Canada')
|
202
|
+
expect(outcome.result).to eq 'Greetings, Christopher! You are the most important citizen of Canada!'
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
180
206
|
context MultiStepComplex do
|
181
207
|
it 'returns the outcome of the last command' do
|
182
208
|
outcome = MultiStepComplex.run(params)
|
data/spec/step_spec.rb
CHANGED
@@ -21,4 +21,36 @@ describe Tzu::Step do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
25
|
+
context '#receives' do
|
26
|
+
context 'when splat_mutator is already defined' do
|
27
|
+
let(:step) { Tzu::Step.new(:step_name) }
|
28
|
+
|
29
|
+
before do
|
30
|
+
step.receives_many do |variable|
|
31
|
+
[1, 2, 3]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'throws error' do
|
36
|
+
expect { step.receives { |var| 'foo'} } .to raise_error(Tzu::InvalidSequence)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context '#receives_many' do
|
42
|
+
context 'when single_mutator is already defined' do
|
43
|
+
let(:step) { Tzu::Step.new(:step_name) }
|
44
|
+
|
45
|
+
before do
|
46
|
+
step.receives do |var|
|
47
|
+
'hello'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'throws error' do
|
52
|
+
expect { step.receives_many { |var| [1, 2, 3] } } .to raise_error(Tzu::InvalidSequence)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
24
56
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tzu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Morgan Bruce
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-07-
|
12
|
+
date: 2015-07-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: '0'
|
112
|
-
description:
|
112
|
+
description: Tzu is a library for issuing commands in Ruby
|
113
113
|
email: morgan@onfido.com
|
114
114
|
executables: []
|
115
115
|
extensions: []
|
@@ -119,6 +119,7 @@ files:
|
|
119
119
|
- README.md
|
120
120
|
- lib/tzu.rb
|
121
121
|
- lib/tzu/core_extensions/string.rb
|
122
|
+
- lib/tzu/errors.rb
|
122
123
|
- lib/tzu/failure.rb
|
123
124
|
- lib/tzu/hooks.rb
|
124
125
|
- lib/tzu/invalid.rb
|
@@ -159,8 +160,7 @@ rubyforge_project:
|
|
159
160
|
rubygems_version: 2.2.2
|
160
161
|
signing_key:
|
161
162
|
specification_version: 4
|
162
|
-
summary:
|
163
|
-
query pollution in the view layer.
|
163
|
+
summary: Standardise and encapsulate your application's actions
|
164
164
|
test_files:
|
165
165
|
- spec/hooks_spec.rb
|
166
166
|
- spec/outcome_spec.rb
|