pipe-ruby 0.3.1 → 1.0.2
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 +5 -5
- data/lib/pipe/config.rb +1 -16
- data/lib/pipe/iterator.rb +6 -21
- data/lib/pipe/reducer.rb +2 -49
- data/lib/pipe/version.rb +1 -1
- data/lib/pipe.rb +0 -1
- data/spec/pipe/config_spec.rb +0 -39
- data/spec/pipe/iterator_spec.rb +13 -53
- data/spec/pipe/reducer_spec.rb +5 -101
- data/spec/spec_helper.rb +3 -0
- metadata +32 -29
- data/.gitignore +0 -14
- data/.rspec +0 -1
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -22
- data/README.md +0 -190
- data/Rakefile +0 -2
- data/lib/pipe/error.rb +0 -38
- data/pipe-ruby.gemspec +0 -26
- data/spec/pipe/error_spec.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fbadf311c963de6b2d2b3afb84a0f2b77289a87a8845113bf50f151ed75f5f2e
|
4
|
+
data.tar.gz: 4ce615623a052ebfbdb74e09ada70331e51d2030af9e0103ea32f01f1545b6d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01ee3e1028218949442ac2ee4367e20664fa338f286214963a61ecfa957339530f029d67fba56f319358c6b31fecc13d2047884f7a7409425ded43871286d904
|
7
|
+
data.tar.gz: 1f5ff71f0f374c2366f97c5acdb8265afb5652fd9819e3d407d7e49a03c0d1f4551fe91d2bc307e2d5ce7a72c9aa573ff1a9b92d5dd77fa8b17599d426e0c90c
|
data/lib/pipe/config.rb
CHANGED
@@ -1,34 +1,19 @@
|
|
1
1
|
module Pipe
|
2
2
|
class Config
|
3
|
-
|
4
|
-
attr_reader :error_handlers, :return_on_error, :skip_on, :stop_on
|
3
|
+
attr_reader :skip_on, :stop_on
|
5
4
|
|
6
5
|
def initialize(
|
7
|
-
error_handlers: [],
|
8
|
-
raise_on_error: true,
|
9
|
-
return_on_error: :subject,
|
10
6
|
skip_on: false,
|
11
7
|
stop_on: false
|
12
8
|
)
|
13
|
-
@error_handlers = error_handlers
|
14
|
-
@raise_on_error = raise_on_error
|
15
|
-
@return_on_error = return_on_error
|
16
9
|
self.skip_on = skip_on
|
17
10
|
self.stop_on = stop_on
|
18
11
|
end
|
19
12
|
|
20
|
-
def error_handler(&block)
|
21
|
-
error_handlers << block if block_given?
|
22
|
-
end
|
23
|
-
|
24
13
|
def break?(*args)
|
25
14
|
stop_on.call(*args) ? true : false
|
26
15
|
end
|
27
16
|
|
28
|
-
def raise_on_error?
|
29
|
-
raise_on_error ? true : false
|
30
|
-
end
|
31
|
-
|
32
17
|
def skip?(*args)
|
33
18
|
skip_on.call(*args) ? true : false
|
34
19
|
end
|
data/lib/pipe/iterator.rb
CHANGED
@@ -9,33 +9,18 @@ module Pipe
|
|
9
9
|
|
10
10
|
def iterate
|
11
11
|
subjects.map { |subject|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
).reduce
|
19
|
-
rescue => e
|
20
|
-
handle_error(:error => e, :subject => subject)
|
21
|
-
subject
|
22
|
-
end
|
12
|
+
Reducer.new(
|
13
|
+
config: config,
|
14
|
+
context: context,
|
15
|
+
subject: subject,
|
16
|
+
through: through
|
17
|
+
).reduce
|
23
18
|
}
|
24
19
|
end
|
25
20
|
|
26
21
|
private
|
27
|
-
|
28
22
|
attr_accessor :config, :context, :subjects, :through
|
29
23
|
|
30
|
-
def handle_error(error:, subject:)
|
31
|
-
if config.raise_on_error?
|
32
|
-
Error.process(
|
33
|
-
:data => { :subject => subject },
|
34
|
-
:error => error,
|
35
|
-
:namespace => IterationError,
|
36
|
-
)
|
37
|
-
end
|
38
|
-
end
|
39
24
|
end
|
40
25
|
end
|
41
26
|
|
data/lib/pipe/reducer.rb
CHANGED
@@ -9,15 +9,8 @@ module Pipe
|
|
9
9
|
|
10
10
|
def reduce
|
11
11
|
through.reduce(subject) { |subj, method|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
process(subj, method)
|
16
|
-
rescue => e
|
17
|
-
payload = {:error => e, :method => method, :subject => subj}
|
18
|
-
handle_error(payload)
|
19
|
-
break error_response(payload)
|
20
|
-
end
|
12
|
+
break subj if config.break?(subj, method, through)
|
13
|
+
process(subj, method)
|
21
14
|
}
|
22
15
|
end
|
23
16
|
|
@@ -25,32 +18,6 @@ module Pipe
|
|
25
18
|
|
26
19
|
attr_accessor :config, :context, :subject, :through
|
27
20
|
|
28
|
-
def error_response(error:, method:, subject:)
|
29
|
-
if config.return_on_error == :subject
|
30
|
-
subject
|
31
|
-
elsif config.return_on_error.respond_to?(:call)
|
32
|
-
config.return_on_error.call(subject, method, error)
|
33
|
-
else
|
34
|
-
config.return_on_error
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def handle_error(error:, method:, subject:)
|
39
|
-
process_error_handlers(
|
40
|
-
:error => error,
|
41
|
-
:method => method,
|
42
|
-
:subject => subject
|
43
|
-
)
|
44
|
-
|
45
|
-
if config.raise_on_error?
|
46
|
-
Error.process(
|
47
|
-
:data => { :method => method, :subject => subject },
|
48
|
-
:error => error,
|
49
|
-
:namespace => ReducerError,
|
50
|
-
)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
21
|
def process(subj, method)
|
55
22
|
if config.skip?(subj, method, through)
|
56
23
|
subj
|
@@ -58,20 +25,6 @@ module Pipe
|
|
58
25
|
context.send(method, subj)
|
59
26
|
end
|
60
27
|
end
|
61
|
-
|
62
|
-
def process_error_handlers(error:, method:, subject:)
|
63
|
-
data = { method: method, subject: subject }
|
64
|
-
|
65
|
-
begin
|
66
|
-
config.error_handlers.each { |handler| handler.call(error, data) }
|
67
|
-
rescue => e
|
68
|
-
Error.process(
|
69
|
-
:data => data,
|
70
|
-
:error => e,
|
71
|
-
:namespace => HandlerError,
|
72
|
-
)
|
73
|
-
end
|
74
|
-
end
|
75
28
|
end
|
76
29
|
end
|
77
30
|
|
data/lib/pipe/version.rb
CHANGED
data/lib/pipe.rb
CHANGED
data/spec/pipe/config_spec.rb
CHANGED
@@ -2,18 +2,6 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Pipe::Config do
|
4
4
|
describe "defaults" do
|
5
|
-
it "sets error handlers to a blank array" do
|
6
|
-
expect(Pipe::Config.new.error_handlers).to eq([])
|
7
|
-
end
|
8
|
-
|
9
|
-
it "sets raise_on_error to true" do
|
10
|
-
expect(Pipe::Config.new.raise_on_error).to eq(true)
|
11
|
-
end
|
12
|
-
|
13
|
-
it "sets return_on_error to :subject" do
|
14
|
-
expect(Pipe::Config.new.return_on_error).to eq(:subject)
|
15
|
-
end
|
16
|
-
|
17
5
|
it "sets skip_on to a proc which returns false" do
|
18
6
|
expect(Pipe::Config.new.skip_on.call).to eq(false)
|
19
7
|
end
|
@@ -23,21 +11,6 @@ describe Pipe::Config do
|
|
23
11
|
end
|
24
12
|
end
|
25
13
|
|
26
|
-
describe "#error_handler" do
|
27
|
-
context "when passed a block" do
|
28
|
-
it "adds the block to the error_handlers array" do
|
29
|
-
config = Pipe::Config.new
|
30
|
-
block = proc { "error handler" }
|
31
|
-
|
32
|
-
expect{ config.error_handler(&block) }
|
33
|
-
.to change{ config.error_handlers.size }
|
34
|
-
.by(1)
|
35
|
-
|
36
|
-
expect(config.error_handlers.last).to eq(block)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
14
|
describe "#break?" do
|
42
15
|
it "returns a truthy version of the result of calling stop_on" do
|
43
16
|
config = Pipe::Config.new(:stop_on => proc { 1 })
|
@@ -57,18 +30,6 @@ describe Pipe::Config do
|
|
57
30
|
end
|
58
31
|
end
|
59
32
|
|
60
|
-
describe "#raise_on_error?" do
|
61
|
-
it "returns a truthy version of raise_on_error" do
|
62
|
-
config = Pipe::Config.new
|
63
|
-
config.raise_on_error = nil
|
64
|
-
expect(config.raise_on_error?).to eq(false)
|
65
|
-
config.raise_on_error = true
|
66
|
-
expect(config.raise_on_error?).to eq(true)
|
67
|
-
config.raise_on_error = "yes"
|
68
|
-
expect(config.raise_on_error?).to eq(true)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
33
|
describe "#skip?" do
|
73
34
|
it "returns a truthy version of the result of calling skip_on" do
|
74
35
|
config = Pipe::Config.new(:skip_on => proc { 42 })
|
data/spec/pipe/iterator_spec.rb
CHANGED
@@ -27,60 +27,20 @@ describe Pipe::Iterator do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
describe "when an error occurs" do
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
raise StandardError, "fail"
|
35
|
-
end
|
36
|
-
iterator = Pipe::Iterator.new(
|
37
|
-
:config => Pipe::Config.new(:raise_on_error => false),
|
38
|
-
:context => Object.new,
|
39
|
-
:subjects => [Object.new],
|
40
|
-
:through => [:to_s]
|
41
|
-
)
|
42
|
-
expect(Pipe::Reducer).to receive(:new).and_return(dub)
|
43
|
-
|
44
|
-
expect{ iterator.iterate }.to_not raise_error
|
45
|
-
end
|
46
|
-
|
47
|
-
it "returns an array of the original items" do
|
48
|
-
dub = Object.new
|
49
|
-
dub.singleton_class.send(:define_method, :reduce) do
|
50
|
-
raise StandardError, "fail"
|
51
|
-
end
|
52
|
-
subjects = [Object.new, Object.new]
|
53
|
-
iterator = Pipe::Iterator.new(
|
54
|
-
:config => Pipe::Config.new(:raise_on_error => false),
|
55
|
-
:context => Object.new,
|
56
|
-
:subjects => subjects,
|
57
|
-
:through => [:to_s]
|
58
|
-
)
|
59
|
-
expect(Pipe::Reducer)
|
60
|
-
.to receive(:new)
|
61
|
-
.and_return(dub)
|
62
|
-
.exactly(2).times
|
63
|
-
|
64
|
-
expect(iterator.iterate).to eq(subjects)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "and Config#raise_on_error is set to true" do
|
69
|
-
it "raises" do
|
70
|
-
dub = Object.new
|
71
|
-
dub.singleton_class.send(:define_method, :reduce) do
|
72
|
-
raise StandardError, "fail"
|
73
|
-
end
|
74
|
-
iterator = Pipe::Iterator.new(
|
75
|
-
:config => Pipe::Config.new(:raise_on_error => true),
|
76
|
-
:context => Object.new,
|
77
|
-
:subjects => [Object.new],
|
78
|
-
:through => [:to_s]
|
79
|
-
)
|
80
|
-
expect(Pipe::Reducer).to receive(:new).and_return(dub)
|
81
|
-
|
82
|
-
expect{ iterator.iterate }.to raise_error
|
30
|
+
it "raises an error" do
|
31
|
+
dub = Object.new
|
32
|
+
dub.singleton_class.send(:define_method, :reduce) do
|
33
|
+
raise StandardError, "fail"
|
83
34
|
end
|
35
|
+
iterator = Pipe::Iterator.new(
|
36
|
+
:config => Pipe::Config.new(),
|
37
|
+
:context => Object.new,
|
38
|
+
:subjects => [Object.new],
|
39
|
+
:through => [:to_s]
|
40
|
+
)
|
41
|
+
expect(Pipe::Reducer).to receive(:new).and_return(dub)
|
42
|
+
|
43
|
+
expect{ iterator.iterate }.to raise_error
|
84
44
|
end
|
85
45
|
end
|
86
46
|
end
|
data/spec/pipe/reducer_spec.rb
CHANGED
@@ -112,120 +112,24 @@ describe Pipe::Reducer do
|
|
112
112
|
expect(reducer.reduce).to eq(subject.to_s.to_sym)
|
113
113
|
end
|
114
114
|
|
115
|
-
it "
|
116
|
-
|
117
|
-
|
118
|
-
config = Pipe::Config.new(:error_handlers => [handler1, handler2])
|
119
|
-
context = Class.new do
|
120
|
-
ExpectedError = Class.new(StandardError)
|
121
|
-
|
122
|
-
def bomb(subject)
|
123
|
-
raise ExpectedError, "BOOM!"
|
124
|
-
end
|
125
|
-
end.new
|
115
|
+
it "does not modify errors" do
|
116
|
+
config = Pipe::Config.new()
|
117
|
+
OneMoreError = Class.new(StandardError)
|
126
118
|
|
127
|
-
expect(handler1).to receive(:call)
|
128
|
-
expect(handler2).to receive(:call)
|
129
|
-
|
130
|
-
expect{
|
131
|
-
Pipe::Reducer.new(
|
132
|
-
:config => config,
|
133
|
-
:context => context,
|
134
|
-
:subject => Object.new,
|
135
|
-
:through => [:bomb]
|
136
|
-
).reduce
|
137
|
-
}.to raise_error
|
138
|
-
end
|
139
|
-
|
140
|
-
it "honors Config#raise_on_error" do
|
141
|
-
config = Pipe::Config.new(:raise_on_error => false)
|
142
119
|
context = Class.new do
|
143
|
-
AnotherExpectedError = Class.new(StandardError)
|
144
|
-
|
145
|
-
def bomb(subject)
|
146
|
-
raise AnotherExpectedError, "BOOM!"
|
147
|
-
end
|
148
|
-
end.new
|
149
|
-
|
150
|
-
expect{
|
151
|
-
Pipe::Reducer.new(
|
152
|
-
:config => config,
|
153
|
-
:context => context,
|
154
|
-
:subject => Object.new,
|
155
|
-
:through => [:bomb]
|
156
|
-
).reduce
|
157
|
-
}.to_not raise_error
|
158
|
-
end
|
159
|
-
|
160
|
-
it "honors Config#return_on_error :subject default" do
|
161
|
-
config = Pipe::Config.new(:raise_on_error => false)
|
162
|
-
context = Class.new do
|
163
|
-
AndAnotherExpectedError = Class.new(StandardError)
|
164
|
-
|
165
|
-
def bomb(subject)
|
166
|
-
raise AndAnotherExpectedError, "BOOM!"
|
167
|
-
end
|
168
|
-
end.new
|
169
|
-
subject = Object.new
|
170
|
-
|
171
|
-
expect(
|
172
|
-
Pipe::Reducer.new(
|
173
|
-
:config => config,
|
174
|
-
:context => context,
|
175
|
-
:subject => subject,
|
176
|
-
:through => [:bomb]
|
177
|
-
).reduce
|
178
|
-
).to eq(subject)
|
179
|
-
end
|
180
|
-
|
181
|
-
it "honors Config#return_on_error callable objects" do
|
182
|
-
subject = Object.new
|
183
|
-
config = Pipe::Config.new(
|
184
|
-
:raise_on_error => false,
|
185
|
-
:return_on_error => proc { |subj, method, e|
|
186
|
-
[subj, method, e.class, e.to_s, :hello]
|
187
|
-
}
|
188
|
-
)
|
189
|
-
context = Class.new do
|
190
|
-
YetAnotherExpectedError = Class.new(StandardError)
|
191
|
-
|
192
|
-
def bomb(subject)
|
193
|
-
raise YetAnotherExpectedError, "BOOM!"
|
194
|
-
end
|
195
|
-
end.new
|
196
|
-
expected = [subject, :bomb, YetAnotherExpectedError, "BOOM!", :hello]
|
197
|
-
|
198
|
-
expect(
|
199
|
-
Pipe::Reducer.new(
|
200
|
-
:config => config,
|
201
|
-
:context => context,
|
202
|
-
:subject => subject,
|
203
|
-
:through => [:bomb]
|
204
|
-
).reduce
|
205
|
-
).to eq(expected)
|
206
|
-
end
|
207
|
-
|
208
|
-
it "returns Config#return_on_error when not callable" do
|
209
|
-
config = Pipe::Config.new(
|
210
|
-
:raise_on_error => false,
|
211
|
-
:return_on_error => :error
|
212
|
-
)
|
213
|
-
context = Class.new do
|
214
|
-
OneMoreError = Class.new(StandardError)
|
215
|
-
|
216
120
|
def bomb(subject)
|
217
121
|
raise OneMoreError, "BOOM!"
|
218
122
|
end
|
219
123
|
end.new
|
220
124
|
|
221
|
-
expect
|
125
|
+
expect{
|
222
126
|
Pipe::Reducer.new(
|
223
127
|
:config => config,
|
224
128
|
:context => context,
|
225
129
|
:subject => Object.new,
|
226
130
|
:through => [:bomb]
|
227
131
|
).reduce
|
228
|
-
|
132
|
+
}.to raise_error(OneMoreError)
|
229
133
|
end
|
230
134
|
end
|
231
135
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pipe-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Dan Matthews
|
7
|
+
- Dan Matthews, Paul Hanyzewski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 12.3.3
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 12.3.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
47
|
+
version: '3.9'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
54
|
+
version: '3.9'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: pry
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,34 +66,39 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
description: ''
|
70
84
|
email:
|
71
|
-
-
|
85
|
+
- devs@teamsnap.com
|
72
86
|
executables: []
|
73
87
|
extensions: []
|
74
88
|
extra_rdoc_files: []
|
75
89
|
files:
|
76
|
-
- ".gitignore"
|
77
|
-
- ".rspec"
|
78
|
-
- Gemfile
|
79
|
-
- LICENSE.txt
|
80
|
-
- README.md
|
81
|
-
- Rakefile
|
82
90
|
- lib/pipe.rb
|
83
91
|
- lib/pipe/config.rb
|
84
|
-
- lib/pipe/error.rb
|
85
92
|
- lib/pipe/ext/inflection.rb
|
86
93
|
- lib/pipe/ext/string.rb
|
87
94
|
- lib/pipe/iterator.rb
|
88
95
|
- lib/pipe/reducer.rb
|
89
96
|
- lib/pipe/version.rb
|
90
|
-
- pipe-ruby.gemspec
|
91
97
|
- spec/pipe/config_spec.rb
|
92
|
-
- spec/pipe/error_spec.rb
|
93
98
|
- spec/pipe/iterator_spec.rb
|
94
99
|
- spec/pipe/reducer_spec.rb
|
95
100
|
- spec/spec_helper.rb
|
96
|
-
homepage:
|
101
|
+
homepage: https://github.com/teamsnap/pipe-ruby
|
97
102
|
licenses:
|
98
103
|
- MIT
|
99
104
|
metadata: {}
|
@@ -103,23 +108,21 @@ require_paths:
|
|
103
108
|
- lib
|
104
109
|
required_ruby_version: !ruby/object:Gem::Requirement
|
105
110
|
requirements:
|
106
|
-
- - "
|
111
|
+
- - ">="
|
107
112
|
- !ruby/object:Gem::Version
|
108
|
-
version: '2.
|
113
|
+
version: '2.3'
|
109
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
115
|
requirements:
|
111
116
|
- - ">="
|
112
117
|
- !ruby/object:Gem::Version
|
113
118
|
version: '0'
|
114
119
|
requirements: []
|
115
|
-
|
116
|
-
rubygems_version: 2.2.2
|
120
|
+
rubygems_version: 3.2.22
|
117
121
|
signing_key:
|
118
122
|
specification_version: 4
|
119
123
|
summary: Ruby implementation of the UNIX pipe
|
120
124
|
test_files:
|
121
125
|
- spec/pipe/config_spec.rb
|
122
|
-
- spec/pipe/error_spec.rb
|
123
126
|
- spec/pipe/iterator_spec.rb
|
124
127
|
- spec/pipe/reducer_spec.rb
|
125
128
|
- spec/spec_helper.rb
|
data/.gitignore
DELETED
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--color
|
data/Gemfile
DELETED
data/LICENSE.txt
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2015 TeamSnap
|
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
DELETED
@@ -1,190 +0,0 @@
|
|
1
|
-
# Pipe
|
2
|
-
|
3
|
-
`pipe-ruby` is an implementation of the UNIX pipe command. It exposes two
|
4
|
-
instance methods, `pipe` and `pipe_each`.
|
5
|
-
|
6
|
-
## Installation
|
7
|
-
|
8
|
-
Add this line to your application's Gemfile:
|
9
|
-
|
10
|
-
```ruby
|
11
|
-
gem "pipe-ruby", :require => "pipe"
|
12
|
-
```
|
13
|
-
|
14
|
-
After bundling, include the `Pipe` module in your class(es)
|
15
|
-
|
16
|
-
```ruby
|
17
|
-
class MyClass
|
18
|
-
include Pipe
|
19
|
-
|
20
|
-
# ...
|
21
|
-
end
|
22
|
-
```
|
23
|
-
|
24
|
-
## Default Usage
|
25
|
-
|
26
|
-
### #pipe
|
27
|
-
|
28
|
-
```ruby
|
29
|
-
pipe(subject, :through => [
|
30
|
-
:method1, :method2#, ...
|
31
|
-
])
|
32
|
-
```
|
33
|
-
|
34
|
-
Just as with the UNIX pipe, `subject` will be passed as the first argument to
|
35
|
-
`method1`. The results of `method1` will be passed to `method2` and on and
|
36
|
-
on. The result of the last method called will be returned from the pipe.
|
37
|
-
|
38
|
-
### #pipe_each
|
39
|
-
|
40
|
-
```ruby
|
41
|
-
pipe_each([subj1, subj2], :through => [
|
42
|
-
:method1, :method2#, ...
|
43
|
-
])
|
44
|
-
```
|
45
|
-
|
46
|
-
`pipe_each` calls `pipe`, passing each individual subject. It will return a
|
47
|
-
mapped array of the responses.
|
48
|
-
|
49
|
-
## Configurable Options
|
50
|
-
|
51
|
-
After implementing the `pipe` method in a few different places, we found that a
|
52
|
-
slightly different version was needed for each use case. `Pipe::Config` allows
|
53
|
-
for this customization per call or per class implementation. There are four
|
54
|
-
configurable options. Here they are with their defaults:
|
55
|
-
|
56
|
-
```ruby
|
57
|
-
Pipe::Config.new(
|
58
|
-
:error_handlers => [], # an array of procs to be called when an error
|
59
|
-
# occurs
|
60
|
-
:raise_on_error => true, # tells Pipe to re-raise errors which occur
|
61
|
-
:return_on_error => :subject, # when an error happens and raise error is false
|
62
|
-
# returns the current value of subject defaultly;
|
63
|
-
# if callable, will return the result of the call
|
64
|
-
# if not callable, will return the value
|
65
|
-
:skip_on => false, # a truthy value or proc which tells pipe to skip
|
66
|
-
# the next method in the `through` array
|
67
|
-
:stop_on => false # a truthy value or proc which tells pipe to stop
|
68
|
-
# processing and return the current value
|
69
|
-
)
|
70
|
-
```
|
71
|
-
|
72
|
-
A `Pipe::Config` object can be passed to the pipe method one of three ways.
|
73
|
-
|
74
|
-
NOTE: The options below are in priority order, meaning an override of the
|
75
|
-
`pipe_config` method will take precedence over an override of the `@pipe_config`
|
76
|
-
instance variable.
|
77
|
-
|
78
|
-
You can pass it to pipe when called:
|
79
|
-
|
80
|
-
```ruby
|
81
|
-
class MyClass
|
82
|
-
include Pipe
|
83
|
-
|
84
|
-
def my_method
|
85
|
-
config = Pipe::Config.new(:raise_on_error => false)
|
86
|
-
subject = Object.new
|
87
|
-
|
88
|
-
pipe(subject, :config => config, :through => [
|
89
|
-
# ...
|
90
|
-
])
|
91
|
-
end
|
92
|
-
|
93
|
-
# ...
|
94
|
-
end
|
95
|
-
```
|
96
|
-
|
97
|
-
Or override the `pipe_config` method:
|
98
|
-
|
99
|
-
```ruby
|
100
|
-
class MyClass
|
101
|
-
include Pipe
|
102
|
-
|
103
|
-
def pipe_config
|
104
|
-
Pipe::Config.new(:raise_on_error => false)
|
105
|
-
end
|
106
|
-
|
107
|
-
# ...
|
108
|
-
end
|
109
|
-
```
|
110
|
-
|
111
|
-
Or you can assign it to the `@pipe_config` instance variable:
|
112
|
-
|
113
|
-
```ruby
|
114
|
-
class MyClass
|
115
|
-
include Pipe
|
116
|
-
|
117
|
-
def initialize
|
118
|
-
@pipe_config = Pipe::Config.new(:raise_on_error => false)
|
119
|
-
end
|
120
|
-
|
121
|
-
# ...
|
122
|
-
end
|
123
|
-
```
|
124
|
-
|
125
|
-
## Error Handling
|
126
|
-
|
127
|
-
As we implemented different versions of `pipe` across our infrastructure, we
|
128
|
-
came across several different error handling needs.
|
129
|
-
|
130
|
-
- logging errors that occur in methods called by pipe without raising them
|
131
|
-
- catching and re-raising errors with additional information so we can still
|
132
|
-
see the real backtrace while also gaining insight into which subject and
|
133
|
-
method combination triggered the error
|
134
|
-
- easily seeing which area of the pipe stack we were in when an error occurred
|
135
|
-
|
136
|
-
The first layer of error handling is the `error_handlers` attribute in
|
137
|
-
`Pipe::Config`. Each proc in this array will be called with two arguments,
|
138
|
-
the actual error object and a context hash containing the method and subject
|
139
|
-
when the error occurred. If an error occurs within one of these handlers it
|
140
|
-
will be re-raised inside the `Pipe::HandlerError` namespace, meaning a
|
141
|
-
`NameError` becomes a `Pipe::HandlerError::NameError`. We also postpend the
|
142
|
-
current method, current subject and original error class to the message.
|
143
|
-
|
144
|
-
NOTE: `Pipe::Config#error_handler` takes a block and adds it to the existing
|
145
|
-
error handlers.
|
146
|
-
|
147
|
-
We have two other namespaces, `Pipe::ReducerError`, which is used when an error
|
148
|
-
occurs inside during `pipe` execution and `Pipe::IteratorError` for errors which
|
149
|
-
occur inside of `pipe_each` execution.
|
150
|
-
|
151
|
-
Whenever an error occurs in execution (but not in error handler processing), the
|
152
|
-
response of `Pipe::Config#raise_on_error?` is checked. If this method returns
|
153
|
-
`true`, the error will be re-raised inside of the appropriate namespace. If it
|
154
|
-
returns `false`, the current value of `subject` will be returned and execution
|
155
|
-
stopped.
|
156
|
-
|
157
|
-
## Skipping / Stopping Execution
|
158
|
-
|
159
|
-
At the beginning of each iteration, `Pipe::Config#stop_on` is called. If it
|
160
|
-
returns truthy, execution will be stopped and the current value of subject will
|
161
|
-
be returned. A falsey response will allow the execution to move forward.
|
162
|
-
|
163
|
-
If not stopped, `Pipe::Config#skip_on` will be called. Truthy responses will
|
164
|
-
cause the current value of subject to be passed to the next iteration without
|
165
|
-
calling the method specified in the current iteration. Falsey responses will
|
166
|
-
allow the specified method to be called.
|
167
|
-
|
168
|
-
Both skip_on and stop_on will receive three arguments when they're called, the
|
169
|
-
current value of subject, the method to be called on this iteration and the
|
170
|
-
value of `#through`.
|
171
|
-
|
172
|
-
## Contributing
|
173
|
-
|
174
|
-
First: please check out our [style guides](https://github.com/teamsnap/guides/tree/master/ruby)...
|
175
|
-
we will hold you to them :)
|
176
|
-
|
177
|
-
1. Fork it ( https://github.com/[my-github-username]/pipe-ruby/fork )
|
178
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
179
|
-
3. Make sure you're green (`bundle exec rspec`)
|
180
|
-
4. Commit your changes (`git commit -am 'Add some feature'`)
|
181
|
-
5. Push to the branch (`git push origin my-new-feature`)
|
182
|
-
6. Create a new Pull Request
|
183
|
-
|
184
|
-
## Testing
|
185
|
-
|
186
|
-
`bundle exec rspec`
|
187
|
-
|
188
|
-
We like to have good coverage of each major feature. Before contributing with a
|
189
|
-
PR, please make sure you've added tests and are fully green.
|
190
|
-
|
data/Rakefile
DELETED
data/lib/pipe/error.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Pipe
|
2
|
-
HandlerError = Module.new
|
3
|
-
IterationError = Module.new
|
4
|
-
ReducerError = Module.new
|
5
|
-
|
6
|
-
class Error
|
7
|
-
def self.process(data: {}, error:, namespace:)
|
8
|
-
new(error).rewrite_as(:namespace => namespace, :data => data)
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize(e)
|
12
|
-
@e = e
|
13
|
-
end
|
14
|
-
|
15
|
-
def rewrite_as(data: {}, namespace:)
|
16
|
-
subclass = find_or_create_subclass(namespace)
|
17
|
-
raise subclass, "#{e} [#{data}, #{e.class}]", e.backtrace
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
attr_reader :e
|
23
|
-
|
24
|
-
def find_or_create_subclass(namespace)
|
25
|
-
part = e.class.name.split("::").last
|
26
|
-
subclass_name = "#{namespace.name}::#{part}"
|
27
|
-
|
28
|
-
begin
|
29
|
-
subclass_name.constantize
|
30
|
-
rescue NameError
|
31
|
-
eval "#{subclass_name} = Class.new(StandardError)"
|
32
|
-
end
|
33
|
-
|
34
|
-
subclass_name.constantize
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
data/pipe-ruby.gemspec
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'pipe/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "pipe-ruby"
|
8
|
-
spec.version = Pipe::VERSION
|
9
|
-
spec.authors = ["Dan Matthews"]
|
10
|
-
spec.email = ["oss@teamsnap.com"]
|
11
|
-
spec.summary = %q{Ruby implementation of the UNIX pipe}
|
12
|
-
spec.description = %q{}
|
13
|
-
spec.homepage = ""
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
spec.required_ruby_version = "~> 2.1"
|
21
|
-
|
22
|
-
spec.add_development_dependency "bundler", "~> 1.7"
|
23
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
-
spec.add_development_dependency "rspec", "~> 3.1"
|
25
|
-
spec.add_development_dependency "pry"
|
26
|
-
end
|
data/spec/pipe/error_spec.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
Namespace = Module.new
|
4
|
-
|
5
|
-
describe Pipe::Error do
|
6
|
-
describe ".process" do
|
7
|
-
it "re-renders the error under the namespace passed" do
|
8
|
-
begin
|
9
|
-
begin
|
10
|
-
not_a_method(:boom)
|
11
|
-
rescue => e
|
12
|
-
Pipe::Error.process(:error => e, :namespace => Namespace)
|
13
|
-
end
|
14
|
-
rescue => e
|
15
|
-
@err = e
|
16
|
-
end
|
17
|
-
|
18
|
-
expect(@err.class.name).to eq("Namespace::NoMethodError")
|
19
|
-
end
|
20
|
-
|
21
|
-
it "adds the original error class to the message" do
|
22
|
-
begin
|
23
|
-
begin
|
24
|
-
not_a_method(:boom)
|
25
|
-
rescue => e
|
26
|
-
Pipe::Error.process(:error => e, :namespace => Namespace)
|
27
|
-
end
|
28
|
-
rescue => e
|
29
|
-
@err = e
|
30
|
-
end
|
31
|
-
|
32
|
-
expect(@err.message).to match(Regexp.new("NoMethodError"))
|
33
|
-
end
|
34
|
-
|
35
|
-
it "adds the data passed to the message" do
|
36
|
-
data = {:one => 1, :two => 2}
|
37
|
-
begin
|
38
|
-
begin
|
39
|
-
not_a_method(:boom)
|
40
|
-
rescue => e
|
41
|
-
Pipe::Error.process(
|
42
|
-
:data => data,
|
43
|
-
:error => e,
|
44
|
-
:namespace => Namespace
|
45
|
-
)
|
46
|
-
end
|
47
|
-
rescue => e
|
48
|
-
@err = e
|
49
|
-
end
|
50
|
-
|
51
|
-
expect(@err.message).to match(Regexp.new("#{data}"))
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|