usecasing 0.1.0 → 0.1.1
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.
- data/lib/usecasing/base.rb +31 -13
- data/lib/usecasing/cyclic_finder.rb +44 -0
- data/lib/usecasing/version.rb +1 -1
- data/lib/usecasing.rb +3 -2
- data/spec/usecase_base_spec.rb +14 -11
- metadata +5 -4
data/lib/usecasing/base.rb
CHANGED
@@ -20,14 +20,15 @@ module UseCase
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def perform(ctx = { })
|
23
|
-
|
23
|
+
any_ciclic, ciclic = CyclicFinder.new(self).cyclic?
|
24
|
+
raise StandardError.new("cyclic detected: #{ciclic}") if any_ciclic
|
25
|
+
execution_order = []
|
26
|
+
build_execution_order(self, execution_order)
|
24
27
|
tx(execution_order, ctx) do |usecase, context|
|
25
28
|
usecase.new(context).perform
|
26
29
|
end
|
27
30
|
end
|
28
31
|
|
29
|
-
private
|
30
|
-
|
31
32
|
def tx(execution_order, context)
|
32
33
|
ctx = Context.new(context)
|
33
34
|
executed = []
|
@@ -47,20 +48,37 @@ module UseCase
|
|
47
48
|
context
|
48
49
|
end
|
49
50
|
|
50
|
-
def build_execution_order(
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
childrens = start_point.dependencies.each do |point|
|
56
|
-
build_execution_order(point, visited).unshift point
|
51
|
+
def build_execution_order(node, result)
|
52
|
+
return result.push(node) if node.dependencies.empty?
|
53
|
+
|
54
|
+
node.dependencies.each do |item|
|
55
|
+
build_execution_order(item, result)
|
57
56
|
end
|
58
|
-
childrens.push(start_point)
|
59
57
|
|
58
|
+
result.push(node)
|
60
59
|
end
|
61
|
-
end
|
62
60
|
|
63
|
-
|
61
|
+
# def build_execution_order
|
62
|
+
# stack = [self]
|
63
|
+
# result = []
|
64
|
+
# visited = {}
|
65
|
+
|
66
|
+
# until stack.empty?
|
67
|
+
# node = stack.last
|
68
|
+
# if(node.dependencies.empty? || visited[node.name])
|
69
|
+
# result.push(stack.pop)
|
70
|
+
# else
|
71
|
+
# stack.push(*(node.dependencies.reverse))
|
72
|
+
# visited[node.name] = true
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
|
76
|
+
# return result
|
77
|
+
|
78
|
+
# end
|
79
|
+
|
80
|
+
end #ClassMethods
|
81
|
+
end #BaseClassMethod
|
64
82
|
|
65
83
|
class Base
|
66
84
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'tsort'
|
3
|
+
|
4
|
+
module UseCase
|
5
|
+
|
6
|
+
class CyclicFinder
|
7
|
+
include TSort
|
8
|
+
|
9
|
+
def initialize(start_point)
|
10
|
+
@start_point = start_point
|
11
|
+
@nodes = discover_nodes
|
12
|
+
end
|
13
|
+
|
14
|
+
def tsort_each_node(&block)
|
15
|
+
@nodes.each &block
|
16
|
+
end
|
17
|
+
|
18
|
+
def tsort_each_child(node, &block)
|
19
|
+
node.dependencies.each &block
|
20
|
+
end
|
21
|
+
|
22
|
+
def cyclic?
|
23
|
+
components = strongly_connected_components
|
24
|
+
result = components.any?{ |component| component.size != 1 }
|
25
|
+
[ result, components.select{|component| component.size != 1 } ]
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def discover_nodes
|
30
|
+
visited = {}
|
31
|
+
stack = [@start_point]
|
32
|
+
result = Set.new
|
33
|
+
until stack.empty?
|
34
|
+
node = stack.pop
|
35
|
+
result.add node
|
36
|
+
stack.push(*(node.dependencies)) if not visited[node]
|
37
|
+
visited[node] = true
|
38
|
+
end
|
39
|
+
|
40
|
+
return result
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/usecasing/version.rb
CHANGED
data/lib/usecasing.rb
CHANGED
data/spec/usecase_base_spec.rb
CHANGED
@@ -226,28 +226,28 @@ describe UseCase::Base do
|
|
226
226
|
|
227
227
|
it 'only rollbacks usecase that ran' do
|
228
228
|
|
229
|
-
UseCaseFailRanThird = Class.new(UseCase::Base) do
|
230
|
-
|
229
|
+
UseCaseFailRanThird = Class.new(UseCase::Base) do
|
230
|
+
|
231
231
|
def rollback
|
232
|
-
context.
|
232
|
+
context.rollback_third = 'true'
|
233
233
|
end
|
234
234
|
|
235
235
|
end
|
236
236
|
|
237
237
|
UseCaseFailRanSecond = Class.new(UseCase::Base) do
|
238
238
|
|
239
|
-
def perform
|
240
|
-
failure(:rollback, 'error')
|
241
|
-
end
|
242
|
-
|
243
|
-
|
244
239
|
def rollback
|
245
|
-
context.rollback_second 'true_2'
|
240
|
+
context.rollback_second = 'true_2'
|
246
241
|
end
|
247
242
|
|
248
243
|
end
|
249
244
|
|
250
245
|
UseCaseFailRanFirst = Class.new(UseCase::Base) do
|
246
|
+
depends UseCaseFailRanSecond
|
247
|
+
|
248
|
+
def perform
|
249
|
+
failure(:rollback, 'error')
|
250
|
+
end
|
251
251
|
|
252
252
|
def rollback
|
253
253
|
context.rollback_first = 'true_1'
|
@@ -256,13 +256,16 @@ describe UseCase::Base do
|
|
256
256
|
end
|
257
257
|
|
258
258
|
UseCaseFailRan = Class.new(UseCase::Base) do
|
259
|
-
depends UseCaseFailRanFirst,
|
259
|
+
depends UseCaseFailRanFirst, UseCaseFailRanThird
|
260
260
|
end
|
261
261
|
|
262
262
|
context = UseCaseFailRan.perform
|
263
|
-
expect(context.
|
263
|
+
expect(context.rollback_third).to_not be
|
264
|
+
expect(context.rollback_second).to be
|
265
|
+
expect(context.rollback_first).to be
|
264
266
|
|
265
267
|
end
|
268
|
+
|
266
269
|
end
|
267
270
|
|
268
271
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: usecasing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- lib/usecasing.rb
|
77
77
|
- lib/usecasing/base.rb
|
78
78
|
- lib/usecasing/context.rb
|
79
|
+
- lib/usecasing/cyclic_finder.rb
|
79
80
|
- lib/usecasing/version.rb
|
80
81
|
- spec/context_spec.rb
|
81
82
|
- spec/spec_helper.rb
|
@@ -95,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
96
|
version: '0'
|
96
97
|
segments:
|
97
98
|
- 0
|
98
|
-
hash:
|
99
|
+
hash: 1663280317763873983
|
99
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
101
|
none: false
|
101
102
|
requirements:
|
@@ -104,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
105
|
version: '0'
|
105
106
|
segments:
|
106
107
|
- 0
|
107
|
-
hash:
|
108
|
+
hash: 1663280317763873983
|
108
109
|
requirements: []
|
109
110
|
rubyforge_project:
|
110
111
|
rubygems_version: 1.8.24
|