lev 1.0.1 → 2.0.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/Gemfile.lock +3 -1
- data/lev.gemspec +1 -0
- data/lib/lev.rb +3 -0
- data/lib/lev/handler.rb +3 -3
- data/lib/lev/object.rb +25 -0
- data/lib/lev/outputs.rb +39 -0
- data/lib/lev/routine.rb +20 -19
- data/lib/lev/version.rb +1 -1
- data/spec/outputs_spec.rb +80 -0
- data/spec/support/create_sprocket.rb +1 -1
- metadata +23 -3
data/Gemfile.lock
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
lev (
|
4
|
+
lev (2.0.1)
|
5
5
|
actionpack (>= 3.0)
|
6
6
|
active_attr
|
7
7
|
activemodel (>= 3.0)
|
8
8
|
activerecord (>= 3.0)
|
9
|
+
hashie
|
9
10
|
transaction_isolation
|
10
11
|
transaction_retry
|
11
12
|
|
@@ -48,6 +49,7 @@ GEM
|
|
48
49
|
debugger-ruby_core_source (1.2.3)
|
49
50
|
diff-lcs (1.2.4)
|
50
51
|
erubis (2.7.0)
|
52
|
+
hashie (2.0.5)
|
51
53
|
i18n (0.6.5)
|
52
54
|
minitest (4.7.5)
|
53
55
|
multi_json (1.8.0)
|
data/lev.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_runtime_dependency "transaction_isolation"
|
25
25
|
spec.add_runtime_dependency "transaction_retry"
|
26
26
|
spec.add_runtime_dependency "active_attr"
|
27
|
+
spec.add_runtime_dependency "hashie"
|
27
28
|
|
28
29
|
spec.add_development_dependency "bundler", "~> 1.3"
|
29
30
|
spec.add_development_dependency "rake"
|
data/lib/lev.rb
CHANGED
@@ -2,12 +2,15 @@ require "action_view"
|
|
2
2
|
require "transaction_isolation"
|
3
3
|
require "transaction_retry"
|
4
4
|
require "active_attr"
|
5
|
+
require "hashie"
|
5
6
|
|
6
7
|
require "lev/version"
|
8
|
+
require "lev/object"
|
7
9
|
require "lev/utilities"
|
8
10
|
require "lev/exceptions"
|
9
11
|
require "lev/better_active_model_errors"
|
10
12
|
require "lev/term_mapper"
|
13
|
+
require "lev/outputs"
|
11
14
|
require "lev/routine"
|
12
15
|
require "lev/handler"
|
13
16
|
require "lev/handle_with"
|
data/lib/lev/handler.rb
CHANGED
@@ -13,7 +13,7 @@ module Lev
|
|
13
13
|
# doing something with it. See Lev::Routine for more information.
|
14
14
|
#
|
15
15
|
# All handlers must:
|
16
|
-
# 2)
|
16
|
+
# 2) call "lev_handler"
|
17
17
|
# 3) implement the 'handle' method which takes no arguments and does the
|
18
18
|
# work the handler is charged with
|
19
19
|
# 4) implement the 'authorized?' method which returns true iff the
|
@@ -32,7 +32,7 @@ module Lev
|
|
32
32
|
# the Handler class would look like:
|
33
33
|
#
|
34
34
|
# class MyHandler
|
35
|
-
#
|
35
|
+
# lev_handler
|
36
36
|
#
|
37
37
|
# paramify :search do
|
38
38
|
# attribute :search_type, type: String
|
@@ -88,7 +88,7 @@ module Lev
|
|
88
88
|
# Example:
|
89
89
|
#
|
90
90
|
# class MyHandler
|
91
|
-
#
|
91
|
+
# lev_handler
|
92
92
|
# protected
|
93
93
|
# def authorized?
|
94
94
|
# # return true iff exec is allowed to be called, e.g. might
|
data/lib/lev/object.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Object
|
2
|
+
|
3
|
+
def self.lev_routine(options={})
|
4
|
+
class_eval do
|
5
|
+
include Lev::Routine unless options[:skip_routine_include]
|
6
|
+
|
7
|
+
# Routine configuration
|
8
|
+
options[:transaction] ||= Lev::TransactionIsolation.mysql_default.symbol
|
9
|
+
@transaction_isolation = Lev::TransactionIsolation.new(options[:transaction])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.lev_handler(options={})
|
14
|
+
class_eval do
|
15
|
+
include Lev::Handler
|
16
|
+
end
|
17
|
+
|
18
|
+
# Do routine configuration
|
19
|
+
options[:skip_routine_include] = true
|
20
|
+
lev_routine(options)
|
21
|
+
|
22
|
+
# Do handler configuration (none currently)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/lev/outputs.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Lev
|
2
|
+
class Outputs < Hashie::Mash
|
3
|
+
|
4
|
+
def initialize(source_hash = nil, default = nil, &blk)
|
5
|
+
@array_created = {}
|
6
|
+
super(source_hash, default, &blk)
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(name, value)
|
10
|
+
if self[name].nil?
|
11
|
+
self[name] = value
|
12
|
+
elsif @array_created[name]
|
13
|
+
self[name].push value
|
14
|
+
else
|
15
|
+
@array_created[name] = true
|
16
|
+
self[name] = [self[name], value]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def each
|
21
|
+
self.each_key do |key|
|
22
|
+
key = key.to_sym
|
23
|
+
if @array_created[key]
|
24
|
+
self[key].each { |value| yield key, value }
|
25
|
+
else
|
26
|
+
yield key, self[key]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def transfer_to(other_outputs, &name_mapping_block)
|
32
|
+
self.each do |name, value|
|
33
|
+
new_name = block_given? ? name_mapping_block.call(name) : name
|
34
|
+
other_outputs.add(new_name, value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/lev/routine.rb
CHANGED
@@ -18,7 +18,7 @@ module Lev
|
|
18
18
|
#
|
19
19
|
# A class becomes a routine by adding:
|
20
20
|
#
|
21
|
-
#
|
21
|
+
# lev_routine
|
22
22
|
#
|
23
23
|
# in its definition.
|
24
24
|
#
|
@@ -36,9 +36,19 @@ module Lev
|
|
36
36
|
# routines aren't typically instantiated with state).
|
37
37
|
#
|
38
38
|
# A routine is automatically run within a transaction. The isolation level
|
39
|
-
# of the routine can be set by
|
40
|
-
#
|
41
|
-
#
|
39
|
+
# of the routine can be set by passing a :transaction option to the lev_routine
|
40
|
+
# call (or to the lev_handler call, if appropriate). The value must be one of
|
41
|
+
#
|
42
|
+
# :no_transaction
|
43
|
+
# :read_uncommitted
|
44
|
+
# :read_committed
|
45
|
+
# :repeatable_read
|
46
|
+
# :serializable
|
47
|
+
#
|
48
|
+
# e.g.
|
49
|
+
#
|
50
|
+
# class MyRoutine
|
51
|
+
# lev_routine transaction: :no_transaction
|
42
52
|
#
|
43
53
|
# As mentioned above, routines can call other routines. While this is of
|
44
54
|
# course possible just by calling the other routine's call method directly,
|
@@ -91,7 +101,7 @@ module Lev
|
|
91
101
|
# context. E.g., in the following class:
|
92
102
|
#
|
93
103
|
# class Routine1
|
94
|
-
#
|
104
|
+
# lev_routine
|
95
105
|
# uses_routine Routine2,
|
96
106
|
# translations: {
|
97
107
|
# inputs: { map: {bar: :foo} }
|
@@ -176,14 +186,9 @@ module Lev
|
|
176
186
|
attr_reader :errors
|
177
187
|
|
178
188
|
def initialize
|
179
|
-
@outputs =
|
189
|
+
@outputs = Outputs.new
|
180
190
|
@errors = Errors.new
|
181
191
|
end
|
182
|
-
|
183
|
-
def add_output(name, value)
|
184
|
-
outputs[name] = [outputs[name], value].flatten.compact
|
185
|
-
outputs[name] = outputs[name].first if outputs[name].size == 1
|
186
|
-
end
|
187
192
|
end
|
188
193
|
|
189
194
|
def self.included(base)
|
@@ -213,11 +218,7 @@ module Lev
|
|
213
218
|
end
|
214
219
|
|
215
220
|
def transaction_isolation
|
216
|
-
@transaction_isolation ||=
|
217
|
-
end
|
218
|
-
|
219
|
-
def default_transaction_isolation
|
220
|
-
TransactionIsolation.mysql_default
|
221
|
+
@transaction_isolation ||= TransactionIsolation.mysql_default
|
221
222
|
end
|
222
223
|
|
223
224
|
def nested_routines
|
@@ -323,8 +324,8 @@ module Lev
|
|
323
324
|
options[:errors_are_fatal] = true if !options.has_key?(:errors_are_fatal)
|
324
325
|
transfer_errors_from(run_result.errors, input_mapper, options[:errors_are_fatal])
|
325
326
|
|
326
|
-
run_result.outputs.
|
327
|
-
|
327
|
+
run_result.outputs.transfer_to(outputs) do |name|
|
328
|
+
output_mapper.map(name)
|
328
329
|
end
|
329
330
|
|
330
331
|
run_result
|
@@ -380,7 +381,7 @@ module Lev
|
|
380
381
|
def runner=(runner)
|
381
382
|
@runner = runner
|
382
383
|
|
383
|
-
if topmost_runner.class.transaction_isolation.weaker_than(self.class.
|
384
|
+
if topmost_runner.class.transaction_isolation.weaker_than(self.class.transaction_isolation)
|
384
385
|
raise IsolationMismatch,
|
385
386
|
"The routine being run has a stronger isolation requirement than " +
|
386
387
|
"the isolation being used by the routine(s) running it; call the " +
|
data/lib/lev/version.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lev::Outputs do
|
4
|
+
|
5
|
+
let(:outputs) { Lev::Outputs.new }
|
6
|
+
|
7
|
+
it "should return a non-array when given just one non-array" do
|
8
|
+
outputs.add(:x, 4)
|
9
|
+
expect(outputs[:x]).to eq 4
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return an array when given just one array" do
|
13
|
+
outputs.add(:x, [1,2])
|
14
|
+
expect(outputs[:x]).to eq [1,2]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should work when given a non-array and an array" do
|
18
|
+
outputs.add(:x, 4)
|
19
|
+
outputs.add(:x, [1,2])
|
20
|
+
expect(outputs[:x]).to eq [4, [1,2]]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should work when given two or three non-arrays" do
|
24
|
+
outputs.add(:x, 1)
|
25
|
+
outputs.add(:x, 2)
|
26
|
+
expect(outputs.x).to eq [1,2]
|
27
|
+
outputs.add(:x, 3)
|
28
|
+
expect(outputs.x).to eq [1,2,3]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should work when given a mix" do
|
32
|
+
outputs.add(:x, [3,4])
|
33
|
+
outputs.add(:x, "hi")
|
34
|
+
outputs.add(:x, {a: 2})
|
35
|
+
expect(outputs.x).to eq [[3,4], "hi", {a: 2}]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should transfer well" do
|
39
|
+
outputs.add(:x, 4)
|
40
|
+
outputs.add(:x, 5)
|
41
|
+
|
42
|
+
other_outputs = Lev::Outputs.new
|
43
|
+
|
44
|
+
outputs.each do |name, value|
|
45
|
+
other_outputs.add(name, value)
|
46
|
+
end
|
47
|
+
|
48
|
+
other_outputs.add(:x, 6)
|
49
|
+
|
50
|
+
expect(other_outputs.x).to eq [4,5,6]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should work via transfer_to with name mapping" do
|
54
|
+
outputs.add(:x, 4)
|
55
|
+
outputs.add(:x, 5)
|
56
|
+
|
57
|
+
other_outputs = Lev::Outputs.new
|
58
|
+
|
59
|
+
outputs.transfer_to(other_outputs) do |name|
|
60
|
+
:y
|
61
|
+
end
|
62
|
+
|
63
|
+
other_outputs.add(:y, 6)
|
64
|
+
expect(other_outputs.y).to eq [4,5,6]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should work via transfer_to without name mapping" do
|
68
|
+
outputs.add(:x, 4)
|
69
|
+
outputs.add(:x, 5)
|
70
|
+
|
71
|
+
other_outputs = Lev::Outputs.new
|
72
|
+
|
73
|
+
outputs.transfer_to(other_outputs)
|
74
|
+
|
75
|
+
other_outputs.add(:y, 6)
|
76
|
+
expect(other_outputs.x).to eq [4,5]
|
77
|
+
expect(other_outputs.y).to eq 6
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lev
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -107,6 +107,22 @@ dependencies:
|
|
107
107
|
- - ! '>='
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: hashie
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
110
126
|
- !ruby/object:Gem::Dependency
|
111
127
|
name: bundler
|
112
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -200,6 +216,8 @@ files:
|
|
200
216
|
- lib/lev/handle_with.rb
|
201
217
|
- lib/lev/handler.rb
|
202
218
|
- lib/lev/handler_helper.rb
|
219
|
+
- lib/lev/object.rb
|
220
|
+
- lib/lev/outputs.rb
|
203
221
|
- lib/lev/routine.rb
|
204
222
|
- lib/lev/term_mapper.rb
|
205
223
|
- lib/lev/transaction_isolation.rb
|
@@ -207,6 +225,7 @@ files:
|
|
207
225
|
- lib/lev/version.rb
|
208
226
|
- spec/create_sprocket_spec.rb
|
209
227
|
- spec/deep_merge_spec.rb
|
228
|
+
- spec/outputs_spec.rb
|
210
229
|
- spec/routine_spec.rb
|
211
230
|
- spec/spec_helper.rb
|
212
231
|
- spec/sprocket_spec.rb
|
@@ -227,7 +246,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
227
246
|
version: '0'
|
228
247
|
segments:
|
229
248
|
- 0
|
230
|
-
hash:
|
249
|
+
hash: 55854544372342664
|
231
250
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
232
251
|
none: false
|
233
252
|
requirements:
|
@@ -236,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
236
255
|
version: '0'
|
237
256
|
segments:
|
238
257
|
- 0
|
239
|
-
hash:
|
258
|
+
hash: 55854544372342664
|
240
259
|
requirements: []
|
241
260
|
rubyforge_project:
|
242
261
|
rubygems_version: 1.8.25
|
@@ -246,6 +265,7 @@ summary: Ride the rails but don't touch them.
|
|
246
265
|
test_files:
|
247
266
|
- spec/create_sprocket_spec.rb
|
248
267
|
- spec/deep_merge_spec.rb
|
268
|
+
- spec/outputs_spec.rb
|
249
269
|
- spec/routine_spec.rb
|
250
270
|
- spec/spec_helper.rb
|
251
271
|
- spec/sprocket_spec.rb
|