pipe-ruby 0.3.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d0eca86ffad3466f3843db7cb3013985bfc1c3bf
4
- data.tar.gz: df2cd7013334b5abce3608c1c85bcd4ca261201a
3
+ metadata.gz: 195a31eb3c9e9ddb6f80a553703cf0501c50b72f
4
+ data.tar.gz: abfdff691c25899d33931d210180c423a612550f
5
5
  SHA512:
6
- metadata.gz: 918395735261b1110693cfa0c08d933e5c7c8ea5e0a73597a3d067a5fc3b29044f36a47b608dfb5a0c911f9df1f3711ff50fbf765bb6a960b91bff22670a30f8
7
- data.tar.gz: 9338db4f769305be5ad63474cca4e4e2ef2fcfebee1f8eb0ade7a2231f992beebfe6e92d842e31be5e823c1d208ba109c911cd72c63f944048214b785d342bf8
6
+ metadata.gz: 6e245799adc6c83fd32ac002b45fafd1475b03beec178e0b99871f4dd891185c912d0bcc7f4dd2bf9f7e2e87777b55a8bbeafbc496a8062b113eb71c86aebed3
7
+ data.tar.gz: 84c1fe2750d276eaf7d673f2040e018102f31c3de8f98ceb7a83c3161e5b46f832241dc58fa4fdac5b850ea33617d5709fbdb5b9ce68cbd278f17e75fc283686
@@ -0,0 +1,4 @@
1
+ # Change Log
2
+
3
+ ## 1.0.0 (2020-02-25)
4
+ - remove pipe-ruby error handling
data/README.md CHANGED
@@ -55,15 +55,9 @@ configurable options. Here they are with their defaults:
55
55
 
56
56
  ```ruby
57
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
58
  :skip_on => false, # a truthy value or proc which tells pipe to skip
66
59
  # the next method in the `through` array
60
+
67
61
  :stop_on => false # a truthy value or proc which tells pipe to stop
68
62
  # processing and return the current value
69
63
  )
@@ -82,7 +76,7 @@ class MyClass
82
76
  include Pipe
83
77
 
84
78
  def my_method
85
- config = Pipe::Config.new(:raise_on_error => false)
79
+ config = Pipe::Config.new(:skip_on => false)
86
80
  subject = Object.new
87
81
 
88
82
  pipe(subject, :config => config, :through => [
@@ -101,7 +95,7 @@ class MyClass
101
95
  include Pipe
102
96
 
103
97
  def pipe_config
104
- Pipe::Config.new(:raise_on_error => false)
98
+ Pipe::Config.new(:skip_on => false)
105
99
  end
106
100
 
107
101
  # ...
@@ -115,45 +109,13 @@ class MyClass
115
109
  include Pipe
116
110
 
117
111
  def initialize
118
- @pipe_config = Pipe::Config.new(:raise_on_error => false)
112
+ @pipe_config = Pipe::Config.new(:skip_on => false)
119
113
  end
120
114
 
121
115
  # ...
122
116
  end
123
117
  ```
124
118
 
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
119
  ## Skipping / Stopping Execution
158
120
 
159
121
  At the beginning of each iteration, `Pipe::Config#stop_on` is called. If it
@@ -1,6 +1,5 @@
1
1
  require "pipe/ext/string"
2
2
  require "pipe/config"
3
- require "pipe/error"
4
3
  require "pipe/iterator"
5
4
  require "pipe/reducer"
6
5
 
@@ -1,34 +1,19 @@
1
1
  module Pipe
2
2
  class Config
3
- attr_accessor :raise_on_error
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
@@ -9,33 +9,18 @@ module Pipe
9
9
 
10
10
  def iterate
11
11
  subjects.map { |subject|
12
- begin
13
- Reducer.new(
14
- config: config,
15
- context: context,
16
- subject: subject,
17
- through: through
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
 
@@ -9,15 +9,8 @@ module Pipe
9
9
 
10
10
  def reduce
11
11
  through.reduce(subject) { |subj, method|
12
- begin
13
- break subj if config.break?(subj, method, through)
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
 
@@ -1,3 +1,3 @@
1
1
  module Pipe
2
- VERSION = "0.3.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -6,8 +6,8 @@ require 'pipe/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "pipe-ruby"
8
8
  spec.version = Pipe::VERSION
9
- spec.authors = ["Dan Matthews"]
10
- spec.email = ["oss@teamsnap.com"]
9
+ spec.authors = ["Dan Matthews, Paul Hanyzewski"]
10
+ spec.email = ["devs@teamsnap.com"]
11
11
  spec.summary = %q{Ruby implementation of the UNIX pipe}
12
12
  spec.description = %q{}
13
13
  spec.homepage = ""
@@ -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 })
@@ -27,60 +27,20 @@ describe Pipe::Iterator do
27
27
  end
28
28
 
29
29
  describe "when an error occurs" do
30
- describe "and Config#raise_on_error is set to false" do
31
- it "does not raise" do
32
- dub = Object.new
33
- dub.singleton_class.send(:define_method, :reduce) do
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
@@ -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 "calls the error handlers when a raise occurs" do
116
- handler1 = Proc.new {}
117
- handler2 = Proc.new {}
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
- ).to eq(:error)
132
+ }.to raise_error(OneMoreError)
229
133
  end
230
134
  end
231
135
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pipe-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 1.0.0
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: 2015-04-12 00:00:00.000000000 Z
11
+ date: 2020-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -68,20 +68,20 @@ dependencies:
68
68
  version: '0'
69
69
  description: ''
70
70
  email:
71
- - oss@teamsnap.com
71
+ - devs@teamsnap.com
72
72
  executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - ".gitignore"
77
77
  - ".rspec"
78
+ - CHANGELOG.md
78
79
  - Gemfile
79
80
  - LICENSE.txt
80
81
  - README.md
81
82
  - Rakefile
82
83
  - lib/pipe.rb
83
84
  - lib/pipe/config.rb
84
- - lib/pipe/error.rb
85
85
  - lib/pipe/ext/inflection.rb
86
86
  - lib/pipe/ext/string.rb
87
87
  - lib/pipe/iterator.rb
@@ -89,7 +89,6 @@ files:
89
89
  - lib/pipe/version.rb
90
90
  - pipe-ruby.gemspec
91
91
  - spec/pipe/config_spec.rb
92
- - spec/pipe/error_spec.rb
93
92
  - spec/pipe/iterator_spec.rb
94
93
  - spec/pipe/reducer_spec.rb
95
94
  - spec/spec_helper.rb
@@ -113,13 +112,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
112
  version: '0'
114
113
  requirements: []
115
114
  rubyforge_project:
116
- rubygems_version: 2.2.2
115
+ rubygems_version: 2.5.2.3
117
116
  signing_key:
118
117
  specification_version: 4
119
118
  summary: Ruby implementation of the UNIX pipe
120
119
  test_files:
121
120
  - spec/pipe/config_spec.rb
122
- - spec/pipe/error_spec.rb
123
121
  - spec/pipe/iterator_spec.rb
124
122
  - spec/pipe/reducer_spec.rb
125
123
  - spec/spec_helper.rb
@@ -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
-
@@ -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