standard-procedure-plumbing 0.3.2 → 0.4.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 +135 -93
- data/lib/plumbing/actor/async.rb +38 -0
- data/lib/plumbing/actor/inline.rb +22 -0
- data/lib/plumbing/actor/kernel.rb +9 -0
- data/lib/plumbing/actor/rails.rb +15 -0
- data/lib/plumbing/actor/threaded.rb +62 -0
- data/lib/plumbing/actor/transporter.rb +61 -0
- data/lib/plumbing/actor.rb +63 -0
- data/lib/plumbing/config.rb +8 -8
- data/lib/plumbing/pipe.rb +2 -3
- data/lib/plumbing/rubber_duck/module.rb +13 -0
- data/lib/plumbing/rubber_duck/object.rb +3 -2
- data/lib/plumbing/rubber_duck.rb +14 -4
- data/lib/plumbing/version.rb +1 -1
- data/lib/plumbing.rb +1 -1
- data/spec/examples/actor_spec.rb +81 -0
- data/spec/examples/pipe_spec.rb +4 -4
- data/spec/examples/rubber_duck_spec.rb +93 -10
- data/spec/plumbing/a_pipe.rb +11 -9
- data/spec/plumbing/actor/transporter_spec.rb +158 -0
- data/spec/plumbing/actor_spec.rb +208 -0
- data/spec/plumbing/pipe_spec.rb +8 -0
- data/spec/plumbing/rubber_duck_spec.rb +46 -48
- metadata +29 -10
- data/lib/plumbing/valve/async.rb +0 -43
- data/lib/plumbing/valve/inline.rb +0 -20
- data/lib/plumbing/valve/message.rb +0 -5
- data/lib/plumbing/valve.rb +0 -71
- data/spec/examples/valve_spec.rb +0 -88
- data/spec/plumbing/valve_spec.rb +0 -167
@@ -0,0 +1,208 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require_relative "../../lib/plumbing/actor/async"
|
4
|
+
require_relative "../../lib/plumbing/actor/threaded"
|
5
|
+
require_relative "../../lib/plumbing/actor/rails"
|
6
|
+
|
7
|
+
RSpec.describe Plumbing::Actor do
|
8
|
+
# standard:disable Lint/ConstantDefinitionInBlock
|
9
|
+
class Counter
|
10
|
+
include Plumbing::Actor
|
11
|
+
async :name, :count, :slow_query, "slowly_increment", "raises_error"
|
12
|
+
attr_reader :name, :count
|
13
|
+
|
14
|
+
def initialize name, initial_value: 0
|
15
|
+
@name = name
|
16
|
+
@count = initial_value
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def slowly_increment
|
22
|
+
sleep 0.2
|
23
|
+
@count += 1
|
24
|
+
end
|
25
|
+
|
26
|
+
def slow_query
|
27
|
+
sleep 0.2
|
28
|
+
@count
|
29
|
+
end
|
30
|
+
|
31
|
+
def raises_error = raise "I'm an error"
|
32
|
+
end
|
33
|
+
|
34
|
+
class StepCounter < Counter
|
35
|
+
async :step_value
|
36
|
+
attr_reader :step_value
|
37
|
+
|
38
|
+
def initialize name, initial_value: 0, step_value: 5
|
39
|
+
super(name, initial_value: initial_value)
|
40
|
+
@step_value = step_value
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def slowly_increment
|
46
|
+
sleep 0.2
|
47
|
+
@count += @step_value
|
48
|
+
end
|
49
|
+
|
50
|
+
def failing_query
|
51
|
+
raise "I'm a failure"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# standard:enable Lint/ConstantDefinitionInBlock
|
55
|
+
|
56
|
+
it "knows which async messages are understood" do
|
57
|
+
expect(Counter.async_messages).to eq [:name, :count, :slow_query, :slowly_increment, :raises_error]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "reuses existing proxy classes" do
|
61
|
+
@counter = Counter.start "inline counter", initial_value: 100
|
62
|
+
@proxy_class = @counter.class
|
63
|
+
|
64
|
+
@counter = Counter.start "another inline counter", initial_value: 200
|
65
|
+
expect(@counter.class).to eq @proxy_class
|
66
|
+
end
|
67
|
+
|
68
|
+
it "includes commands and queries from the superclass" do
|
69
|
+
expect(StepCounter.async_messages).to eq [:name, :count, :slow_query, :slowly_increment, :raises_error, :step_value]
|
70
|
+
|
71
|
+
@step_counter = StepCounter.start "step counter", initial_value: 100, step_value: 10
|
72
|
+
|
73
|
+
expect(@step_counter.count.await).to eq 100
|
74
|
+
expect(@step_counter.step_value.await).to eq 10
|
75
|
+
@step_counter.slowly_increment
|
76
|
+
expect(@step_counter.count.await).to eq 110
|
77
|
+
end
|
78
|
+
|
79
|
+
context "inline" do
|
80
|
+
around :example do |example|
|
81
|
+
Plumbing.configure mode: :inline, &example
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns the result from a message immediately" do
|
85
|
+
@counter = Counter.start "inline counter", initial_value: 100
|
86
|
+
@time = Time.now
|
87
|
+
|
88
|
+
expect(@counter.name.await).to eq "inline counter"
|
89
|
+
expect(@counter.count.await).to eq 100
|
90
|
+
expect(Time.now - @time).to be < 0.1
|
91
|
+
|
92
|
+
expect(@counter.slow_query.await).to eq 100
|
93
|
+
expect(Time.now - @time).to be > 0.1
|
94
|
+
end
|
95
|
+
|
96
|
+
it "sends all commands immediately" do
|
97
|
+
@counter = Counter.start "inline counter", initial_value: 100
|
98
|
+
@time = Time.now
|
99
|
+
|
100
|
+
@counter.slowly_increment
|
101
|
+
|
102
|
+
expect(@counter.count.await).to eq 101
|
103
|
+
expect(Time.now - @time).to be > 0.1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
[:threaded, :async].each do |mode|
|
108
|
+
context mode.to_s do
|
109
|
+
around :example do |example|
|
110
|
+
Sync do
|
111
|
+
Plumbing.configure mode: mode, &example
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "performs queries in the background and waits for the response" do
|
116
|
+
@counter = Counter.start "async counter", initial_value: 100
|
117
|
+
@time = Time.now
|
118
|
+
|
119
|
+
expect(@counter.name.await).to eq "async counter"
|
120
|
+
expect(@counter.count.await).to eq 100
|
121
|
+
expect(Time.now - @time).to be < 0.1
|
122
|
+
|
123
|
+
expect(@counter.slow_query.await).to eq 100
|
124
|
+
expect(Time.now - @time).to be > 0.1
|
125
|
+
end
|
126
|
+
|
127
|
+
it "performs queries ignoring the response and returning immediately" do
|
128
|
+
@counter = Counter.start "threaded counter", initial_value: 100
|
129
|
+
@time = Time.now
|
130
|
+
|
131
|
+
@counter.slow_query
|
132
|
+
|
133
|
+
expect(Time.now - @time).to be < 0.1
|
134
|
+
end
|
135
|
+
|
136
|
+
it "performs commands in the background and returning immediately" do
|
137
|
+
@counter = Counter.start "threaded counter", initial_value: 100
|
138
|
+
@time = Time.now
|
139
|
+
|
140
|
+
@counter.slowly_increment
|
141
|
+
expect(Time.now - @time).to be < 0.1
|
142
|
+
|
143
|
+
# wait for the background task to complete
|
144
|
+
expect(101).to become_equal_to { @counter.count.await }
|
145
|
+
expect(Time.now - @time).to be > 0.1
|
146
|
+
end
|
147
|
+
|
148
|
+
it "re-raises exceptions when checking the result" do
|
149
|
+
@counter = Counter.start "failure"
|
150
|
+
|
151
|
+
expect { @counter.raises_error.await }.to raise_error "I'm an error"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "does not raise exceptions if ignoring the result" do
|
155
|
+
@counter = Counter.start "failure"
|
156
|
+
|
157
|
+
expect { @counter.raises_error }.not_to raise_error
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "threaded" do
|
163
|
+
around :example do |example|
|
164
|
+
Plumbing.configure mode: :threaded, &example
|
165
|
+
end
|
166
|
+
|
167
|
+
# standard:disable Lint/ConstantDefinitionInBlock
|
168
|
+
class Record
|
169
|
+
include GlobalID::Identification
|
170
|
+
attr_reader :id
|
171
|
+
def initialize id
|
172
|
+
@id = id
|
173
|
+
end
|
174
|
+
|
175
|
+
def == other
|
176
|
+
other.id == @id
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class Actor
|
181
|
+
include Plumbing::Actor
|
182
|
+
async :get_object_id, :get_object
|
183
|
+
|
184
|
+
private def get_object_id(record) = record.object_id
|
185
|
+
private def get_object(record) = record
|
186
|
+
end
|
187
|
+
# standard:enable Lint/ConstantDefinitionInBlock
|
188
|
+
|
189
|
+
it "packs and unpacks arguments when sending them across threads" do
|
190
|
+
@actor = Actor.start
|
191
|
+
@record = Record.new "999"
|
192
|
+
|
193
|
+
@object_id = @actor.get_object_id(@record).await
|
194
|
+
|
195
|
+
expect(@object_id).to_not eq @record.object_id
|
196
|
+
end
|
197
|
+
|
198
|
+
it "packs and unpacks results when sending them across threads" do
|
199
|
+
@actor = Actor.start
|
200
|
+
@record = Record.new "999"
|
201
|
+
|
202
|
+
@object = @actor.get_object(@record).await
|
203
|
+
|
204
|
+
expect(@object.id).to eq @record.id
|
205
|
+
expect(@object.object_id).to_not eq @record.object_id
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
data/spec/plumbing/pipe_spec.rb
CHANGED
@@ -5,72 +5,70 @@ RSpec.describe Plumbing::RubberDuck do
|
|
5
5
|
class Duck
|
6
6
|
def quack = "Quack"
|
7
7
|
|
8
|
-
def swim place
|
9
|
-
"Swim in #{place}"
|
10
|
-
end
|
8
|
+
def swim(place) = "Swim in #{place}"
|
11
9
|
|
12
|
-
def fly
|
13
|
-
"Fly #{block.call}"
|
14
|
-
end
|
10
|
+
def fly(&block) = "Fly #{block.call}"
|
15
11
|
end
|
16
12
|
# standard:enable Lint/ConstantDefinitionInBlock
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
context "defining rubber ducks" do
|
15
|
+
it "verifies that an object matches the RubberDuck type" do
|
16
|
+
@duck_type = described_class.define :quack, :swim, :fly
|
17
|
+
@duck = Duck.new
|
21
18
|
|
22
|
-
|
23
|
-
|
19
|
+
expect(@duck_type.verify(@duck)).to eq @duck
|
20
|
+
end
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
it "casts the object to a duck type" do
|
23
|
+
@duck_type = described_class.define :quack, :swim, :fly
|
24
|
+
@duck = Duck.new
|
28
25
|
|
29
|
-
|
26
|
+
@proxy = @duck.as @duck_type
|
30
27
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
28
|
+
expect(@proxy).to be_kind_of Plumbing::RubberDuck::Proxy
|
29
|
+
expect(@proxy).to respond_to :quack
|
30
|
+
expect(@proxy.quack).to eq "Quack"
|
31
|
+
expect(@proxy).to respond_to :swim
|
32
|
+
expect(@proxy.swim("the river")).to eq "Swim in the river"
|
33
|
+
expect(@proxy).to respond_to :fly
|
34
|
+
expect(@proxy.fly { "ducky fly" }).to eq "Fly ducky fly"
|
35
|
+
end
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
it "does not forward methods that are not part of the duck type" do
|
38
|
+
@duck_type = described_class.define :swim, :fly
|
39
|
+
@duck = Duck.new
|
43
40
|
|
44
|
-
|
41
|
+
@proxy = @duck.as @duck_type
|
45
42
|
|
46
|
-
|
47
|
-
|
43
|
+
expect(@proxy).to_not respond_to :quack
|
44
|
+
end
|
48
45
|
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
it "does not wrap rubber ducks in a proxy" do
|
47
|
+
@duck_type = described_class.define :swim, :fly
|
48
|
+
@duck = Duck.new
|
52
49
|
|
53
|
-
|
50
|
+
@proxy = @duck.as @duck_type
|
54
51
|
|
55
|
-
|
56
|
-
|
52
|
+
expect(@proxy.as(@duck_type)).to eq @proxy
|
53
|
+
end
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
it "allows rubber ducks to be expanded and cast to other types" do
|
56
|
+
@quackers = described_class.define :quack
|
57
|
+
@swimming_bird = described_class.define :swim, :fly
|
58
|
+
@duck = Duck.new
|
62
59
|
|
63
|
-
|
64
|
-
|
60
|
+
@swimmer = @duck.as @swimming_bird
|
61
|
+
@quacker = @swimmer.as @quackers
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
expect(@swimmer).to respond_to :swim
|
64
|
+
expect(@quacker).to respond_to :quack
|
65
|
+
end
|
69
66
|
|
70
|
-
|
71
|
-
|
72
|
-
|
67
|
+
it "raises a TypeError if the object does not respond to the given methods" do
|
68
|
+
@cow_type = described_class.define :moo, :chew
|
69
|
+
@duck = Duck.new
|
73
70
|
|
74
|
-
|
71
|
+
expect { @cow_type.verify(@duck) }.to raise_error(TypeError)
|
72
|
+
end
|
75
73
|
end
|
76
74
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: standard-procedure-plumbing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rahoul Baruah
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
12
|
-
dependencies:
|
11
|
+
date: 2024-09-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: globalid
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description: A composable event pipeline and sequential pipelines of operations
|
14
28
|
email:
|
15
29
|
- rahoulb@echodek.co
|
@@ -20,6 +34,13 @@ files:
|
|
20
34
|
- README.md
|
21
35
|
- Rakefile
|
22
36
|
- lib/plumbing.rb
|
37
|
+
- lib/plumbing/actor.rb
|
38
|
+
- lib/plumbing/actor/async.rb
|
39
|
+
- lib/plumbing/actor/inline.rb
|
40
|
+
- lib/plumbing/actor/kernel.rb
|
41
|
+
- lib/plumbing/actor/rails.rb
|
42
|
+
- lib/plumbing/actor/threaded.rb
|
43
|
+
- lib/plumbing/actor/transporter.rb
|
23
44
|
- lib/plumbing/config.rb
|
24
45
|
- lib/plumbing/custom_filter.rb
|
25
46
|
- lib/plumbing/error.rb
|
@@ -31,27 +52,25 @@ files:
|
|
31
52
|
- lib/plumbing/pipeline/contracts.rb
|
32
53
|
- lib/plumbing/pipeline/operations.rb
|
33
54
|
- lib/plumbing/rubber_duck.rb
|
55
|
+
- lib/plumbing/rubber_duck/module.rb
|
34
56
|
- lib/plumbing/rubber_duck/object.rb
|
35
57
|
- lib/plumbing/rubber_duck/proxy.rb
|
36
58
|
- lib/plumbing/types.rb
|
37
|
-
- lib/plumbing/valve.rb
|
38
|
-
- lib/plumbing/valve/async.rb
|
39
|
-
- lib/plumbing/valve/inline.rb
|
40
|
-
- lib/plumbing/valve/message.rb
|
41
59
|
- lib/plumbing/version.rb
|
42
60
|
- spec/become_equal_to_matcher.rb
|
61
|
+
- spec/examples/actor_spec.rb
|
43
62
|
- spec/examples/pipe_spec.rb
|
44
63
|
- spec/examples/pipeline_spec.rb
|
45
64
|
- spec/examples/rubber_duck_spec.rb
|
46
|
-
- spec/examples/valve_spec.rb
|
47
65
|
- spec/plumbing/a_pipe.rb
|
66
|
+
- spec/plumbing/actor/transporter_spec.rb
|
67
|
+
- spec/plumbing/actor_spec.rb
|
48
68
|
- spec/plumbing/custom_filter_spec.rb
|
49
69
|
- spec/plumbing/filter_spec.rb
|
50
70
|
- spec/plumbing/junction_spec.rb
|
51
71
|
- spec/plumbing/pipe_spec.rb
|
52
72
|
- spec/plumbing/pipeline_spec.rb
|
53
73
|
- spec/plumbing/rubber_duck_spec.rb
|
54
|
-
- spec/plumbing/valve_spec.rb
|
55
74
|
- spec/plumbing_spec.rb
|
56
75
|
- spec/spec_helper.rb
|
57
76
|
homepage: https://github.com/standard-procedure/plumbing
|
@@ -76,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
95
|
- !ruby/object:Gem::Version
|
77
96
|
version: '0'
|
78
97
|
requirements: []
|
79
|
-
rubygems_version: 3.5.
|
98
|
+
rubygems_version: 3.5.12
|
80
99
|
signing_key:
|
81
100
|
specification_version: 4
|
82
101
|
summary: Plumbing - various pipelines for your ruby application
|
data/lib/plumbing/valve/async.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require "async"
|
2
|
-
require "async/semaphore"
|
3
|
-
require "timeout"
|
4
|
-
|
5
|
-
module Plumbing
|
6
|
-
module Valve
|
7
|
-
class Async
|
8
|
-
attr_reader :target
|
9
|
-
|
10
|
-
def initialize target
|
11
|
-
@target = target
|
12
|
-
@queue = []
|
13
|
-
@semaphore = ::Async::Semaphore.new(1)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Ask the target to answer the given message
|
17
|
-
def ask(message, *args, **params, &block)
|
18
|
-
task = @semaphore.async do
|
19
|
-
@target.send message, *args, **params, &block
|
20
|
-
end
|
21
|
-
Timeout.timeout(timeout) do
|
22
|
-
task.wait
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Tell the target to execute the given message
|
27
|
-
def tell(message, *args, **params, &block)
|
28
|
-
@semaphore.async do |task|
|
29
|
-
@target.send message, *args, **params, &block
|
30
|
-
rescue
|
31
|
-
nil
|
32
|
-
end
|
33
|
-
nil
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def timeout
|
39
|
-
Plumbing.config.timeout
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Plumbing
|
2
|
-
module Valve
|
3
|
-
class Inline
|
4
|
-
def initialize target
|
5
|
-
@target = target
|
6
|
-
end
|
7
|
-
|
8
|
-
# Ask the target to answer the given message
|
9
|
-
def ask(message, ...)
|
10
|
-
@target.send(message, ...)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Tell the target to execute the given message
|
14
|
-
def tell(message, ...)
|
15
|
-
@target.send(message, ...)
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/plumbing/valve.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
require_relative "valve/inline"
|
2
|
-
|
3
|
-
module Plumbing
|
4
|
-
module Valve
|
5
|
-
def self.included base
|
6
|
-
base.extend ClassMethods
|
7
|
-
end
|
8
|
-
|
9
|
-
module ClassMethods
|
10
|
-
# Create a new valve instance and build a proxy for it using the current mode
|
11
|
-
# @return [Plumbing::Valve::Base] the proxy for the valve instance
|
12
|
-
def start(*, **, &)
|
13
|
-
build_proxy_for(new(*, **, &))
|
14
|
-
end
|
15
|
-
|
16
|
-
# Define the queries that this valve can answer
|
17
|
-
# @param names [Array<Symbol>] the names of the queries
|
18
|
-
def query(*names) = queries.concat(names.map(&:to_sym))
|
19
|
-
|
20
|
-
# List the queries that this valve can answer
|
21
|
-
def queries = @queries ||= []
|
22
|
-
|
23
|
-
# Define the commands that this valve can execute
|
24
|
-
# @param names [Array<Symbol>] the names of the commands
|
25
|
-
def command(*names) = commands.concat(names.map(&:to_sym))
|
26
|
-
|
27
|
-
# List the commands that this valve can execute
|
28
|
-
def commands = @commands ||= []
|
29
|
-
|
30
|
-
def inherited subclass
|
31
|
-
subclass.commands.concat commands
|
32
|
-
subclass.queries.concat queries
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def build_proxy_for(target)
|
38
|
-
proxy_class_for(target.class).new(target)
|
39
|
-
end
|
40
|
-
|
41
|
-
def proxy_class_for target_class
|
42
|
-
Plumbing.config.valve_proxy_class_for(target_class) || register_valve_proxy_class_for(target_class)
|
43
|
-
end
|
44
|
-
|
45
|
-
def proxy_base_class = const_get "Plumbing::Valve::#{Plumbing.config.mode.to_s.capitalize}"
|
46
|
-
|
47
|
-
def register_valve_proxy_class_for target_class
|
48
|
-
Plumbing.config.register_valve_proxy_class_for(target_class, build_proxy_class)
|
49
|
-
end
|
50
|
-
|
51
|
-
def build_proxy_class
|
52
|
-
Class.new(proxy_base_class).tap do |proxy_class|
|
53
|
-
queries.each do |query|
|
54
|
-
proxy_class.define_method query do |*args, ignore_result: false, **params, &block|
|
55
|
-
ignore_result ? tell(query, *args, **params, &block) : ask(query, *args, **params, &block)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
commands.each do |command|
|
60
|
-
proxy_class.define_method command do |*args, **params, &block|
|
61
|
-
tell(command, *args, **params, &block)
|
62
|
-
nil
|
63
|
-
rescue
|
64
|
-
nil
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
data/spec/examples/valve_spec.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
RSpec.describe "Valve examples" do
|
4
|
-
# standard:disable Lint/ConstantDefinitionInBlock
|
5
|
-
class Employee
|
6
|
-
include Plumbing::Valve
|
7
|
-
query :name, :job_title, :greet_slowly
|
8
|
-
command :promote
|
9
|
-
|
10
|
-
def initialize(name)
|
11
|
-
@name = name
|
12
|
-
@job_title = "Sales assistant"
|
13
|
-
end
|
14
|
-
|
15
|
-
attr_reader :name, :job_title
|
16
|
-
|
17
|
-
def promote
|
18
|
-
sleep 0.5
|
19
|
-
@job_title = "Sales manager"
|
20
|
-
end
|
21
|
-
|
22
|
-
def greet_slowly
|
23
|
-
sleep 0.2
|
24
|
-
"H E L L O"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
# standard:enable Lint/ConstantDefinitionInBlock
|
28
|
-
|
29
|
-
context "inline" do
|
30
|
-
it "queries an object" do
|
31
|
-
Plumbing.configure mode: :inline do
|
32
|
-
@person = Employee.start "Alice"
|
33
|
-
|
34
|
-
expect(@person.name).to eq "Alice"
|
35
|
-
expect(@person.job_title).to eq "Sales assistant"
|
36
|
-
|
37
|
-
@time = Time.now
|
38
|
-
expect(@person.greet_slowly).to eq "H E L L O"
|
39
|
-
expect(Time.now - @time).to be > 0.1
|
40
|
-
|
41
|
-
@time = Time.now
|
42
|
-
expect(@person.greet_slowly(ignore_result: true)).to be_nil
|
43
|
-
expect(Time.now - @time).to be > 0.1
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
it "commands an object" do
|
48
|
-
Plumbing.configure mode: :inline do
|
49
|
-
@person = Employee.start "Alice"
|
50
|
-
|
51
|
-
@person.promote
|
52
|
-
|
53
|
-
expect(@person.job_title).to eq "Sales manager"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context "async" do
|
59
|
-
around :example do |example|
|
60
|
-
Plumbing.configure mode: :async do
|
61
|
-
Kernel::Async(&example)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
it "queries an object" do
|
66
|
-
@person = Employee.start "Alice"
|
67
|
-
|
68
|
-
expect(@person.name).to eq "Alice"
|
69
|
-
expect(@person.job_title).to eq "Sales assistant"
|
70
|
-
|
71
|
-
@time = Time.now
|
72
|
-
expect(@person.greet_slowly).to eq "H E L L O"
|
73
|
-
expect(Time.now - @time).to be > 0.1
|
74
|
-
|
75
|
-
@time = Time.now
|
76
|
-
expect(@person.greet_slowly(ignore_result: true)).to be_nil
|
77
|
-
expect(Time.now - @time).to be < 0.1
|
78
|
-
end
|
79
|
-
|
80
|
-
it "commands an object" do
|
81
|
-
@person = Employee.start "Alice"
|
82
|
-
|
83
|
-
@person.promote
|
84
|
-
|
85
|
-
expect(@person.job_title).to eq "Sales manager"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|