composable_operations 0.7.0 → 0.8.0

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: 5ac9f54ccfaf7e9e03e47174f435b00f536764c9
4
- data.tar.gz: ee9f3b4c7a5185403b4b418a3860bb05af007891
3
+ metadata.gz: af1c4603f14d42656d794709d5db02bc69014f7b
4
+ data.tar.gz: c3b7bcd54b0747b0173f1e01050cb0f1a307247c
5
5
  SHA512:
6
- metadata.gz: 10dbdfddb4ad3957b07e95316518902b6880f2ef3e739ce298b143824cc568402eba18aadfcd47c0907684351175abb5612f860ee2736daf0afc58ef79f3d3b5
7
- data.tar.gz: 12f3736f3056b60b79a18e9645a267f5f7f4718f89a384b231d4cc3f60b88c63f9144757b6f90a0f2bb809b9766d1fedfb88aa08822778988257867c9d43418a
6
+ metadata.gz: 7cd11e937b6183a4b628d02d9b9ade6400a6dd9c831410a6905ab21e06d88db3b17117e8a06261e6064119f092b760f66053db87d8d2c8294eb5e6af31915e64
7
+ data.tar.gz: 6647e6ba14819d2d6fe07d339ac5290d449038ed2096f33f8c1ea64903202379adb1acd707586332b6c2c809c2d8bdbfe05cff3bbf9f33cbdde232dba05027a8
@@ -54,7 +54,7 @@ module ComposableOperations
54
54
  operation.perform
55
55
 
56
56
  if operation.failed?
57
- fail operation.message, operation.result, operation.backtrace
57
+ fail operation.exception
58
58
  elsif operation.halted?
59
59
  halt operation.message, operation.result
60
60
  end
@@ -15,7 +15,7 @@ module ComposableOperations
15
15
  operation = new(*args)
16
16
  operation.perform
17
17
 
18
- raise exception, operation.message, operation.backtrace if operation.failed?
18
+ raise operation.exception if operation.failed?
19
19
 
20
20
  operation.result
21
21
  end
@@ -86,6 +86,7 @@ module ComposableOperations
86
86
  attr_reader :result
87
87
  attr_reader :message
88
88
  attr_reader :backtrace
89
+ attr_reader :exception
89
90
 
90
91
  def initialize(*args)
91
92
  named_input_parameters = args.shift(self.class.arity)
@@ -136,18 +137,42 @@ module ComposableOperations
136
137
  attr_writer :message
137
138
  attr_writer :result
138
139
  attr_writer :backtrace
140
+ attr_writer :exception
139
141
 
140
142
  def execute
141
143
  raise NotImplementedError, "#{name}#execute not implemented"
142
144
  end
143
145
 
144
- def fail(message = nil, return_value = nil, backtrace = caller)
146
+ def fail(*args)
145
147
  raise "Operation execution has already been aborted" if halted? or failed?
148
+ exception, message, backtrace = nil, nil, nil
149
+
150
+ case args.length
151
+ when 1
152
+ value = args[0]
153
+ if Exception === value
154
+ exception = value
155
+ elsif Class === value && Exception > value
156
+ exception = value
157
+ message = value.message
158
+ backtrace = value.backtrace
159
+ else
160
+ message = value
161
+ end
162
+ when 2, 3
163
+ exception, message, backtrace = args[0], args[1], args[2]
164
+ end
165
+
166
+ backtrace ||= caller
167
+ exception ||= self.class.exception
168
+ exception = Class === exception ? exception.new(message) : exception
169
+ exception.set_backtrace(backtrace)
146
170
 
147
171
  self.state = :failed
148
172
  self.backtrace = backtrace
149
173
  self.message = message
150
- throw :halt, return_value
174
+ self.exception = exception
175
+ throw :halt, nil
151
176
  end
152
177
 
153
178
  def halt(message = nil, return_value = nil)
@@ -1,3 +1,3 @@
1
1
  module ComposableOperations
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+ describe ComposableOperations::Operation, "that always fails:" do
4
+ let(:failing_operation) do
5
+ Class.new(described_class) do
6
+ def execute
7
+ fail "Operation failed"
8
+ end
9
+ end
10
+ end
11
+
12
+ context "When no default exception has been specified" do
13
+ it "should raise an error when executed" do
14
+ expect { failing_operation.perform }.to raise_error(ComposableOperations::OperationError, "Operation failed")
15
+ end
16
+
17
+ context "when manually instantiated and executed" do
18
+ subject(:failing_operation_instance) do
19
+ operation = failing_operation.new
20
+ operation.perform
21
+ operation
22
+ end
23
+
24
+ it "should have nil as result" do
25
+ failing_operation_instance.result.should be_nil
26
+ end
27
+
28
+ it "should have failed" do
29
+ failing_operation_instance.should be_failed
30
+ end
31
+
32
+ it "should have a message" do
33
+ failing_operation_instance.message.should_not be_nil
34
+ end
35
+
36
+ it "should have an exception of type OperationError whose message is 'Operation failed'" do
37
+ failing_operation_instance.exception.should be_kind_of(ComposableOperations::OperationError)
38
+ failing_operation_instance.exception.message.should be == 'Operation failed'
39
+ end
40
+ end
41
+
42
+ context "when extended with a finalizer" do
43
+ let(:supervisor) { mock("Supervisor") }
44
+
45
+ let(:failing_operation_with_finalizer) do
46
+ supervisor = supervisor()
47
+ Class.new(failing_operation) do
48
+ after { supervisor.notify }
49
+ end
50
+ end
51
+
52
+ subject(:failing_operation_with_finalizer_instance) do
53
+ failing_operation_with_finalizer.new
54
+ end
55
+
56
+ it "should execute the finalizers" do
57
+ supervisor.should_receive(:notify)
58
+ failing_operation_with_finalizer_instance.perform
59
+ end
60
+ end
61
+ end
62
+
63
+ context "When a default exception has been specified" do
64
+ let(:custom_exception) { Class.new(RuntimeError) }
65
+
66
+ subject(:failing_operation_with_custom_default_exception) do
67
+ custom_exception = custom_exception()
68
+ Class.new(failing_operation) do
69
+ raises custom_exception
70
+ end
71
+ end
72
+
73
+ it "should raise the custom exeception when executed" do
74
+ expect { failing_operation_with_custom_default_exception.perform }.
75
+ to raise_error(custom_exception, "Operation failed")
76
+ end
77
+
78
+ context "when manually instantiated and executed" do
79
+ subject(:failing_operation_with_custom_default_exception_instance) do
80
+ operation = failing_operation_with_custom_default_exception.new
81
+ operation.perform
82
+ operation
83
+ end
84
+
85
+ it "should have an exception of the custom exception type whose message is 'Operation failed'" do
86
+ failing_operation_with_custom_default_exception_instance.exception.should be_kind_of(custom_exception)
87
+ failing_operation_with_custom_default_exception_instance.exception.message.should be == 'Operation failed'
88
+ end
89
+ end
90
+ end
91
+
92
+ context "When a custom exception has been specified" do
93
+ let(:custom_exception) { Class.new(RuntimeError) }
94
+ subject(:failing_operation_with_custom_exception) do
95
+ custom_exception = self.custom_exception
96
+ Class.new(described_class) do
97
+ define_method(:execute) do
98
+ fail custom_exception, "Operation failed"
99
+ end
100
+ end
101
+ end
102
+
103
+ it "should raise the custom exeception when executed" do
104
+ expect { failing_operation_with_custom_exception.perform }.
105
+ to raise_error(custom_exception, "Operation failed")
106
+ end
107
+
108
+ context "when manually instantiated and executed" do
109
+ subject(:failing_operation_with_custom_exception_instance) do
110
+ operation = failing_operation_with_custom_exception.new
111
+ operation.perform
112
+ operation
113
+ end
114
+
115
+ it "should have an exception of the custom exception type whose message is 'Operation failed'" do
116
+ failing_operation_with_custom_exception_instance.exception.should be_kind_of(custom_exception)
117
+ failing_operation_with_custom_exception_instance.exception.message.should be == 'Operation failed'
118
+ end
119
+ end
120
+
121
+ context "when used in a composed operation" do
122
+ let(:failing_composed_operation) do
123
+ ComposableOperations::ComposedOperation.compose(failing_operation_with_custom_exception)
124
+ end
125
+
126
+ it "should raise the custom exception that is thrown by the inner operation when executed" do
127
+ expect { failing_composed_operation.perform }.
128
+ to raise_error(custom_exception, "Operation failed")
129
+ end
130
+
131
+ context "when this composed operation is manually instantiated and executed" do
132
+ subject(:failing_composed_operation_instance) do
133
+ operation = failing_composed_operation.new
134
+ operation.perform
135
+ operation
136
+ end
137
+
138
+ it "should have an exception of the custom exception type whose message is 'Operation failed'" do
139
+ failing_composed_operation_instance.exception.should be_kind_of(custom_exception)
140
+ failing_composed_operation_instance.exception.message.should be == 'Operation failed'
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+
@@ -2,6 +2,35 @@ require 'spec_helper'
2
2
 
3
3
  describe ComposableOperations::ComposedOperation, "input forwarding:" do
4
4
 
5
+ describe "An operation pipeline that first constructs an array with two elements and then passes it to an operation that accepts two input parameters and returns the second one" do
6
+
7
+ let(:array_generator) do
8
+ Class.new(ComposableOperations::Operation) do
9
+ def execute
10
+ [:first_element, :second_element]
11
+ end
12
+ end
13
+ end
14
+
15
+ let(:extractor) do
16
+ Class.new(ComposableOperations::Operation) do
17
+ processes :first_parameter, :second_parameter
18
+ def execute
19
+ second_parameter
20
+ end
21
+ end
22
+ end
23
+
24
+ subject(:pipeline) do
25
+ ComposableOperations::ComposedOperation.compose(array_generator, extractor)
26
+ end
27
+
28
+ it "should return the correct element" do
29
+ result = pipeline.perform
30
+ result.should == :second_element
31
+ end
32
+ end
33
+
5
34
  describe "An operation pipeline that first constructs an enumerator, then passes it from operation to operation and finally returns it as the result" do
6
35
 
7
36
  let(:enum_generator) do
@@ -46,81 +46,6 @@ describe ComposableOperations::Operation do
46
46
 
47
47
  end
48
48
 
49
- context "that always fails" do
50
-
51
- let(:failing_operation) do
52
- Class.new(described_class) do
53
- def execute
54
- fail "Operation failed"
55
- end
56
- end
57
- end
58
-
59
- subject(:failing_operation_instance) do
60
- failing_operation.new
61
- end
62
-
63
- before(:each) do
64
- failing_operation_instance.perform
65
- end
66
-
67
- it "should have nil as result" do
68
- failing_operation_instance.result.should be_nil
69
- end
70
-
71
- it "should have failed" do
72
- failing_operation_instance.should be_failed
73
- end
74
-
75
- it "should have a message" do
76
- failing_operation_instance.message.should_not be_nil
77
- end
78
-
79
- it "should raise an error when executed using the class method perform" do
80
- expect { failing_operation.perform }.to raise_error("Operation failed")
81
- end
82
-
83
- context "when extended with a finalizer" do
84
-
85
- let(:supervisor) { mock("Supervisor") }
86
-
87
- let(:failing_operation_instance_with_finalizer) do
88
- supervisor = supervisor()
89
- Class.new(failing_operation) do
90
- after { supervisor.notify }
91
- end
92
- end
93
-
94
- subject(:failing_operation_instance_with_finalizer_instance) do
95
- failing_operation_instance_with_finalizer.new
96
- end
97
-
98
- it "should execute the finalizers" do
99
- supervisor.should_receive(:notify)
100
- failing_operation_instance_with_finalizer_instance.perform
101
- end
102
-
103
- end
104
-
105
- context "when configured to raise a custom exception" do
106
-
107
- let(:custom_exception) { Class.new(RuntimeError) }
108
-
109
- subject(:failing_operation_with_custom_exception) do
110
- custom_exception = custom_exception()
111
- Class.new(failing_operation) do
112
- raises custom_exception
113
- end
114
- end
115
-
116
- it "should raise the custom exeception when executed using the class method perform" do
117
- expect { failing_operation_with_custom_exception.perform }.to raise_error(custom_exception, "Operation failed")
118
- end
119
-
120
- end
121
-
122
- end
123
-
124
49
  context "that always returns something when executed" do
125
50
 
126
51
  let(:simple_operation) do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: composable_operations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Tennhard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-02 00:00:00.000000000 Z
11
+ date: 2013-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: smart_properties
@@ -105,6 +105,7 @@ files:
105
105
  - lib/composable_operations/version.rb
106
106
  - spec/composable_operations/composed_operation_spec.rb
107
107
  - spec/composable_operations/control_flow_spec.rb
108
+ - spec/composable_operations/exception_handling_spec.rb
108
109
  - spec/composable_operations/operation_input_forwarding_spec.rb
109
110
  - spec/composable_operations/operation_input_processing_spec.rb
110
111
  - spec/composable_operations/operation_spec.rb
@@ -136,6 +137,7 @@ summary: Tool set for operation pipelines.
136
137
  test_files:
137
138
  - spec/composable_operations/composed_operation_spec.rb
138
139
  - spec/composable_operations/control_flow_spec.rb
140
+ - spec/composable_operations/exception_handling_spec.rb
139
141
  - spec/composable_operations/operation_input_forwarding_spec.rb
140
142
  - spec/composable_operations/operation_input_processing_spec.rb
141
143
  - spec/composable_operations/operation_spec.rb