lou 0.2.0 → 0.2.1

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: 34aac868cb5bf73797d2b41155f717ee85ffe7fd
4
- data.tar.gz: 5cc5bada947c03de042098b226b85179e394ed53
3
+ metadata.gz: 6c875d55f836118c55dd4e3bedc345fb9839dbb6
4
+ data.tar.gz: 12c8985d3aaf1bf744a980f0135e456e8a04b860
5
5
  SHA512:
6
- metadata.gz: c8d9d453b8dfd91ed8ad960a45086d042bedd7678d2231d99a9aa74ca5b587b825aa98c4447833a8672a0048744ac9670123524b0e788a1c5566bc9810a23984
7
- data.tar.gz: 2451c3a54ea3c4ba91f5a3d031711882da48d34156e475e18cc1cc59bf9ed140a423630eeae252d4155b6eda5e8f095e2a40fd2721f8fb499f6fa13024310345
6
+ metadata.gz: 7eb8dedecc8d4589abcb8f83d7e37c00d32689e2710f1f58a6bbea709f198276d2e30c5ab889c3237a39f88e0e9b5691a640c4d3f859542748bfe618b5f9075d
7
+ data.tar.gz: 38e5554d87650c7df1f439d387091a6b749265b1941fe71edbaa74987ea74efcd4a593dc7521f37a1af0e76bf381325291b5722dbe8a48759d3a011c412e411a
data/README.md CHANGED
@@ -17,6 +17,9 @@ require 'lou'
17
17
  class HashTransformer
18
18
  extend Lou::Transformer
19
19
 
20
+ # optional
21
+ reverse_on RuntimeError
22
+
20
23
  step.up do |x|
21
24
  x.merge(a_new_key: 'this is new')
22
25
  end.down do |x|
@@ -41,7 +44,9 @@ original = HashTransformer.reverse(result)
41
44
  # {:an_old_key=>"this is old"}
42
45
  ~~~
43
46
 
44
- The transforms are applied in the order that they're defined using the ~apply~ function, with each transform receiving the result of the previous one. The process can be reversed using the ~reverse~ function. Note that for each step, the input is the result of the previous step.
47
+ The steps are applied in the order that they're defined, when the ~apply~ method is called, with each step receiving the result of the previous one. The process can be reversed using the ~reverse~ method. Note that for each step, the input is the result of the previous step.
48
+
49
+ If ~reverse_on~ is defined, then any completed steps will be reversed if the exception specified is raised.
45
50
 
46
51
  Transformers inherit the steps of their parent class, so it's possible to reuse steps by using inheritance.
47
52
 
@@ -3,29 +3,50 @@ require 'lou/transformer/step'
3
3
 
4
4
  module Lou
5
5
  module Transformer
6
+ # never raise this...
7
+ class NeverError < StandardError; end
8
+
6
9
  def self.extended(base)
7
10
  base.class_eval do
8
11
  class_attribute(:steps)
9
12
  self.steps = []
13
+ class_attribute(:error_class)
14
+ self.error_class = Lou::Transformer::NeverError
10
15
  end
11
16
  end
12
17
 
18
+ def reverse_on(error)
19
+ self.error_class = error
20
+ end
21
+
13
22
  def step
14
23
  Step.new.tap do |t|
15
24
  steps << t
16
25
  end
17
26
  end
18
27
 
19
- def apply(input)
20
- steps.each do |t|
21
- input = t.apply(input)
28
+ def apply(input, total_steps = steps.count)
29
+ applied_steps = 0
30
+ begin
31
+ steps.last(total_steps).each do |t|
32
+ input = t.apply(input)
33
+ applied_steps += 1
34
+ end
35
+ rescue error_class => e
36
+ total_steps == steps.count ? reverse(input, applied_steps) : raise(e)
22
37
  end
23
38
  input
24
39
  end
25
40
 
26
- def reverse(output)
27
- steps.reverse_each do |t|
28
- output = t.reverse(output)
41
+ def reverse(output, total_steps = steps.count)
42
+ reversed_steps = 0
43
+ begin
44
+ steps.first(total_steps).reverse_each do |t|
45
+ output = t.reverse(output)
46
+ reversed_steps += 1
47
+ end
48
+ rescue error_class => e
49
+ total_steps == steps.count ? apply(output, reversed_steps) : raise(e)
29
50
  end
30
51
  output
31
52
  end
data/lib/lou/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lou
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.1'
3
3
  end
@@ -110,5 +110,93 @@ module Lou
110
110
  end
111
111
  end
112
112
  end
113
+
114
+ context 'when an error is raised' do
115
+ let(:klass) do
116
+ Class.new do
117
+ extend Lou::Transformer
118
+ step.up { |_| fail 'error on up' }.down { |_| fail 'error on down' }
119
+ end
120
+ end
121
+
122
+ describe '#apply' do
123
+ it 'raises the exception' do
124
+ expect { klass.apply('foo') }.to raise_error('error on up')
125
+ end
126
+ end
127
+
128
+ describe '#reverse' do
129
+ it 'raises the exception' do
130
+ expect { klass.reverse('bar') }.to raise_error('error on down')
131
+ end
132
+ end
133
+ end
134
+
135
+ context 'when #reverse_on has been set' do
136
+ let(:parent) do
137
+ Class.new do
138
+ extend Lou::Transformer
139
+
140
+ class SpecialError < StandardError; end
141
+
142
+ reverse_on SpecialError
143
+ end
144
+ end
145
+
146
+ let(:target) { instance_double('Target') }
147
+
148
+ context 'and an error is raised on the first step' do
149
+ let(:klass) do
150
+ Class.new(parent) do
151
+ step.up { |_| fail SpecialError }.down { |x| x.destroy(1); x }
152
+ step.up { |x| x.create(2); x }.down { |_| fail SpecialError }
153
+ end
154
+ end
155
+
156
+ describe '#apply' do
157
+ it 'reverses no steps when the specified error is raised' do
158
+ expect(target).to_not receive(:create)
159
+ expect(target).to_not receive(:destroy)
160
+ klass.apply(target)
161
+ end
162
+ end
163
+
164
+ describe '#reverse' do
165
+ it 'applies no steps when the specified error is raised' do
166
+ expect(target).to_not receive(:destroy)
167
+ expect(target).to_not receive(:create)
168
+ klass.reverse(target)
169
+ end
170
+ end
171
+ end
172
+
173
+ context 'and an error is raised part-way through the transform' do
174
+ let(:klass) do
175
+ Class.new(parent) do
176
+ step.up { |x| x.create(1); x }.down { |x| x.destroy(1); x }
177
+ step.up { |_| fail SpecialError }.down { |_| fail SpecialError }
178
+ step.up { |x| x.create(3); x }.down { |x| x.destroy(3); x }
179
+ end
180
+ end
181
+
182
+ let(:target) { instance_double('Target') }
183
+
184
+ describe '#apply' do
185
+ it 'reverses all successfully applied steps when the specified error is raised' do
186
+ expect(target).to receive(:create).once.with(1).ordered
187
+ expect(target).to receive(:destroy).once.with(1).ordered
188
+ klass.apply(target)
189
+ end
190
+ end
191
+
192
+ describe '#reverse' do
193
+ it 'reapplies all successfully reversed steps when the specified error is raised' do
194
+ expect(target).to receive(:destroy).once.with(3).ordered
195
+ expect(target).to receive(:create).once.with(3).ordered
196
+ klass.reverse(target)
197
+ end
198
+ end
199
+ end
200
+ end
113
201
  end
114
202
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lou
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iain Beeston