simple_pipeline 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 677d2ff5729eb15c9fd13f634606d462279001de
4
- data.tar.gz: 781a8d2a9772234ce73be2ba1d42c87b75ff6ecc
3
+ metadata.gz: a4a484ac10baf55839867a7e23333575331af1f2
4
+ data.tar.gz: fa4e96d7ef40d54df3d08b274c167a2c21a1e57d
5
5
  SHA512:
6
- metadata.gz: 4545e19ba08add3987a1cd729c478917098d754df9557a3fe79f15309df96fa40a71c4a6ffe9fc5b8f0c20c68bded8a00adb3f7800ebf617ef9d69e8b9499e56
7
- data.tar.gz: 84e0c38fa8984b5843c861d6f5fcffd3ed4053cce508273d4b6fb483b680b0045c7c8ef5a0e7a3e85041095bde656f5541eb7d692104ffce20f192af2b770437
6
+ metadata.gz: be5125980ed3f7164f294d2db6a431c0f72769af801308ac95654d85e3fb76bcec280d0c092b30b88e6fc37cd3c52eafa0244a7246567a44bf0258dfc3f708aa
7
+ data.tar.gz: bc1d2a74e196b4101067f409b9d7e0e69c9ea4941814f08fa69776b46ff170423f9b5e853e8cbe6f7b1298758b505c46b230aedf4677e21e6faa0b8ceeeec641
data/README.md CHANGED
@@ -32,7 +32,7 @@ payload = {:some_key => some_value}
32
32
  pipeline.process payload
33
33
  ```
34
34
 
35
- **SimplePipeline** will call the ```process``` method on each of the pipes in the order that they were added to the pipeline.
35
+ **SimplePipeline** will call the ```process``` method on each of the pipes in the order that they were added to the pipeline. As long as the pipes don't maintain state, you can call ```SimplePipeline#process``` as many times as you want, potentially with each run working with a different payload object.
36
36
 
37
37
  ## Pipes
38
38
 
@@ -46,6 +46,24 @@ class Pipe1
46
46
  end
47
47
  ```
48
48
 
49
+ If your object does not have a ```process``` method, you can still use it as a pipe, but you will need to explicitly state the method to invoke when adding the pipe to the pipeline. Likewise, the specified method must accept a single payload argument.
50
+
51
+ ```ruby
52
+ class AlternatePipe
53
+ def execute (input)
54
+ # Do something with the input
55
+ end
56
+
57
+ def invoke (param1, param2)
58
+ # Do something else
59
+ end
60
+ end
61
+
62
+ pipeline.add AlternativePipe.new, :process_method => :execute # => OK
63
+
64
+ pipeline.add AlternativePipe.new, :process_method => :invoke # => throws ArgumentError
65
+ ```
66
+
49
67
  ## Payload
50
68
 
51
69
  The **payload** can be an Array, Hash, or any other Ruby object. Individual pipes have the responsibility to know what to do with the payload that is passed into the ```process``` method.
@@ -116,7 +134,11 @@ pipeline.add pipe, :continue_on_error? => [ArgumentError, NameError]
116
134
  pipeline.add pipe, :continue_on_error? => Exception
117
135
  ```
118
136
 
119
- After the pipeline finishes executing, you can call ```pipeline.errors``` to get an Array of errors that were caught during execution.
137
+ After the pipeline finishes executing, you can call ```SimplePipeline#errors``` to get an Array of errors that were caught during execution. This Array will clear itself if the pipeline is run again.
138
+
139
+ ```ruby
140
+ pipeline.errors # => Array of errors caught during last run
141
+ ```
120
142
 
121
143
  ## Related Projects
122
144
 
@@ -0,0 +1,24 @@
1
+ class SimplePipeline
2
+ module Validation
3
+ class Error < StandardError; end
4
+
5
+ def self.included (base)
6
+ base.extend(ClassMethods)
7
+ base.class_variable_set(:@@validations, [])
8
+ end
9
+
10
+ module ClassMethods
11
+ def validate (validation_lambda)
12
+ raise ArgumentException "invalid validation - expect lambda instead of #{validation_lambda.class}" unless (validation_lambda.is_a? Proc) && validation_lambda.lambda?
13
+
14
+ self.class_variable_get(:@@validations) << validation_lambda
15
+ end
16
+ end
17
+
18
+ def validate (payload)
19
+ self.class.class_variable_get(:@@validations).each do |validation_lambda|
20
+ raise SimplePipeline::Validation::Error.new "#{self.class} - #{payload}" unless validation_lambda.call(payload)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  class SimplePipeline
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require "simple_pipeline/timeout"
2
+ require "simple_pipeline/validation"
2
3
  require "simple_pipeline/version"
3
4
 
4
5
 
@@ -8,12 +9,12 @@ class SimplePipeline
8
9
 
9
10
  def initialize
10
11
  @pipe_order = []
11
- @pipe_config = {}
12
+ @pipe_options = {}
12
13
  @errors = []
13
14
  end
14
15
 
15
- def add (pipe, params = {})
16
- process_method = params[:process_method] || :process
16
+ def add (pipe, options = {})
17
+ process_method = options[:process_method] || :process
17
18
 
18
19
  begin
19
20
  raise ArgumentError, "invalid pipe - incorrect number of arguments for #{process_method}() method (should be 1)" unless pipe.class.instance_method(process_method).arity == 1
@@ -22,7 +23,7 @@ class SimplePipeline
22
23
  end
23
24
 
24
25
  @pipe_order << pipe
25
- @pipe_config[pipe] = params
26
+ @pipe_options[pipe] = options
26
27
 
27
28
  return pipe
28
29
  end
@@ -32,8 +33,11 @@ class SimplePipeline
32
33
  end
33
34
 
34
35
  def process (payload)
36
+ @errors.clear
37
+
35
38
  @pipe_order.each do |pipe|
36
39
  begin
40
+ validate_payload(pipe, payload)
37
41
  invoke_process_with_timeout(pipe, payload, get_timeout(pipe))
38
42
  rescue
39
43
  raise $! unless continue_on_error?($!, pipe)
@@ -47,7 +51,7 @@ class SimplePipeline
47
51
  private
48
52
 
49
53
  def continue_on_error? (e, pipe)
50
- config_value = @pipe_config[pipe][:continue_on_error?]
54
+ config_value = @pipe_options[pipe][:continue_on_error?]
51
55
 
52
56
  return false if config_value.nil? || config_value == false
53
57
  return true if config_value == true
@@ -70,12 +74,16 @@ class SimplePipeline
70
74
  end
71
75
 
72
76
  def get_process_method (pipe)
73
- @pipe_config[pipe][:process_method] || :process
77
+ @pipe_options[pipe][:process_method] || :process
74
78
  end
75
79
 
76
80
  def get_timeout (pipe)
77
- timeout = @pipe_config[pipe][:timeout]
81
+ timeout = @pipe_options[pipe][:timeout]
78
82
  timeout = pipe.timeout if timeout.nil? && (pipe.is_a? SimplePipeline::Timeout)
79
83
  return timeout
80
84
  end
85
+
86
+ def validate_payload (pipe, payload)
87
+ pipe.validate(payload) if (pipe.is_a? SimplePipeline::Validation)
88
+ end
81
89
  end
@@ -38,6 +38,18 @@ class ExceptionPipe
38
38
  end
39
39
  end
40
40
 
41
+ class ValidationPipe
42
+ include SimplePipeline::Validation
43
+
44
+ validate ->(payload) { payload[:must_exist] }
45
+ validate ->(payload) { payload[:must_be_false] == false }
46
+ validate ->(payload) { payload[:a][:b] == 1 }
47
+
48
+ def process (payload)
49
+ payload[:test_value] *= 10
50
+ end
51
+ end
52
+
41
53
  describe SimplePipeline do
42
54
  it "should support three normal pipes" do
43
55
  pipeline = SimplePipeline.new
@@ -132,4 +144,26 @@ describe SimplePipeline do
132
144
 
133
145
  expect(payload[:test_value]).to eq 100
134
146
  end
147
+
148
+ it "should support pipes with payload validation" do
149
+ pipeline = SimplePipeline.new
150
+ pipeline.add ValidationPipe.new
151
+
152
+ payload = {:test_value => 10}
153
+
154
+ expect {
155
+ pipeline.process(payload)
156
+ }.to raise_error(SimplePipeline::Validation::Error)
157
+
158
+ payload = {
159
+ :test_value => 10,
160
+ :must_exist => "abc",
161
+ :must_be_false => false,
162
+ :a => {:b => 1}
163
+ }
164
+
165
+ pipeline.process(payload)
166
+
167
+ expect(payload[:test_value]).to eq 100
168
+ end
135
169
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Wong
@@ -53,6 +53,7 @@ files:
53
53
  - Rakefile
54
54
  - lib/simple_pipeline.rb
55
55
  - lib/simple_pipeline/timeout.rb
56
+ - lib/simple_pipeline/validation.rb
56
57
  - lib/simple_pipeline/version.rb
57
58
  - simple_pipeline.gemspec
58
59
  - spec/simple_pipeline_spec.rb