composable_operations 0.7.0 → 0.8.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: 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