startback 0.12.2 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/startback/context/h_factory.rb +43 -0
- data/lib/startback/context.rb +25 -34
- data/lib/startback/event/agent.rb +1 -1
- data/lib/startback/event/engine.rb +17 -99
- data/lib/startback/event.rb +2 -0
- data/lib/startback/model.rb +6 -0
- data/lib/startback/operation.rb +5 -0
- data/lib/startback/services.rb +11 -0
- data/lib/startback/support/data_object.rb +71 -0
- data/lib/startback/support/world.rb +54 -0
- data/lib/startback/support.rb +2 -0
- data/lib/startback/version.rb +2 -2
- data/lib/startback.rb +2 -0
- data/spec/spec_helper.rb +13 -1
- data/spec/unit/context/test_fork.rb +3 -4
- data/spec/unit/context/test_with_world.rb +20 -0
- data/spec/unit/context/test_world.rb +17 -0
- data/spec/unit/support/test_data_object.rb +156 -0
- data/spec/unit/support/test_world.rb +72 -0
- data/tasks/test.rake +2 -9
- metadata +17 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d5d880b8e9dfdeecdd68e78400468a2765dffbcf39866860daef9ac86a8096d
|
4
|
+
data.tar.gz: 6bf01ece248ca741ed4a590ab5458c8f94bda465c315951cfb0797fa49ae4fe9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f21d629f5733aea63bdfd21199aae51208d16751e398a373cef0a72cf4fcbceb083046c7f1ec61f9ed4791c2e4621a787229f438622a35a28a9ca2591ec5f90
|
7
|
+
data.tar.gz: c77c9f93fc437a8c803782d226bd6f9c30497f1eb238a6244526262fd5c24e148b322d01d46ed8bd81d907b9851a9789e1774abaec5dccd63fefc8a0da50eeb1
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Startback
|
2
|
+
class Context
|
3
|
+
module HFactory
|
4
|
+
|
5
|
+
def h(hash)
|
6
|
+
h_factor!(self.new, hash)
|
7
|
+
end
|
8
|
+
|
9
|
+
def h_factor!(context, hash)
|
10
|
+
h_factories.each do |f|
|
11
|
+
f.call(context, hash)
|
12
|
+
end
|
13
|
+
context
|
14
|
+
end
|
15
|
+
|
16
|
+
def h_factories
|
17
|
+
@h_factories ||= []
|
18
|
+
end
|
19
|
+
|
20
|
+
def h_factory(&factory)
|
21
|
+
h_factories << factory
|
22
|
+
end
|
23
|
+
|
24
|
+
###
|
25
|
+
|
26
|
+
def h_dump!(context, hash = {})
|
27
|
+
h_dumpers.each do |d|
|
28
|
+
context.instance_exec(hash, &d)
|
29
|
+
end
|
30
|
+
hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def h_dumpers
|
34
|
+
@h_dumpers ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
def h_dump(&dumper)
|
38
|
+
h_dumpers << dumper
|
39
|
+
end
|
40
|
+
|
41
|
+
end # module HFactory
|
42
|
+
end # class Context
|
43
|
+
end # module Startback
|
data/lib/startback/context.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Startback
|
2
2
|
#
|
3
3
|
# Defines an execution context for Startback applications, and provides
|
4
|
-
# a cached factory for related abstractions (see `factor`)
|
4
|
+
# a cached factory for related abstractions (see `factor`), and an
|
5
|
+
# extensible world, statically and dynamically.
|
5
6
|
#
|
6
7
|
# In web application, an instance of a context can be set on the Rack
|
7
8
|
# environment, using Context::Middleware.
|
@@ -48,46 +49,36 @@ module Startback
|
|
48
49
|
# convert them to wathever log format is necessary.
|
49
50
|
attr_accessor :logger
|
50
51
|
|
51
|
-
|
52
|
-
|
52
|
+
require_relative 'context/h_factory'
|
53
|
+
extend(Context::HFactory)
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
def h_factor!(context, hash)
|
59
|
-
h_factories.each do |f|
|
60
|
-
f.call(context, hash)
|
61
|
-
end
|
62
|
-
context
|
63
|
-
end
|
64
|
-
|
65
|
-
def h_factories
|
66
|
-
@h_factories ||= []
|
67
|
-
end
|
55
|
+
def initialize
|
56
|
+
super
|
57
|
+
yield(self) if block_given?
|
58
|
+
end
|
68
59
|
|
69
|
-
|
70
|
-
|
71
|
-
end
|
60
|
+
attr_writer :_world
|
61
|
+
protected :_world=
|
72
62
|
|
73
|
-
|
63
|
+
def self.world(who, &block)
|
64
|
+
@_world ||= Support::World.new
|
65
|
+
@_world = @_world.factory(who, &block)
|
66
|
+
end
|
74
67
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
hash
|
80
|
-
end
|
68
|
+
def self.factor_world(context)
|
69
|
+
@_world ||= Support::World.new
|
70
|
+
@_world.with_scope(context)
|
71
|
+
end
|
81
72
|
|
82
|
-
|
83
|
-
|
84
|
-
|
73
|
+
def world
|
74
|
+
@_world ||= self.class.factor_world(self)
|
75
|
+
end
|
85
76
|
|
86
|
-
|
87
|
-
|
77
|
+
def with_world(world)
|
78
|
+
dup do |ctx|
|
79
|
+
ctx._world = self.world.with(world)
|
88
80
|
end
|
89
|
-
|
90
|
-
end # class << self
|
81
|
+
end
|
91
82
|
|
92
83
|
# Factors an instance of `clazz`, which must be a Context-related
|
93
84
|
# abstraction (i.e. its constructor takes the context as last parameters).
|
@@ -1,18 +1,14 @@
|
|
1
1
|
require 'rack'
|
2
|
-
require 'webrick'
|
3
2
|
require 'startback'
|
4
3
|
module Startback
|
5
4
|
class Event
|
6
5
|
#
|
7
6
|
# This class is the starting point of event handling in
|
8
7
|
# Startback. It holds a Bus instance to which emitters
|
9
|
-
# and listeners can connect
|
10
|
-
# the listening part to start an infinite loop (ServerEngine).
|
8
|
+
# and listeners can connect.
|
11
9
|
#
|
12
|
-
# The Engine
|
13
|
-
#
|
14
|
-
# and method `on_health_check` overriden to run specific
|
15
|
-
# checks.
|
10
|
+
# The Engine exposes a rack app (.rack_app) with a /healthcheck webservice.
|
11
|
+
# It is supposed to be mounted to a webserver such as puma.
|
16
12
|
#
|
17
13
|
# This class goes hand in hand with the `startback:engine`
|
18
14
|
# docker image. It can be extended by subclasses to override
|
@@ -22,15 +18,13 @@ module Startback
|
|
22
18
|
# - on_health_check to check specific health conditions
|
23
19
|
# - create_agents to instantiate all listening agents
|
24
20
|
# (unless auto_create_agents is used)
|
21
|
+
# - rack_app if you want to customize the API running
|
25
22
|
#
|
26
23
|
class Engine
|
27
24
|
include Support::Robustness
|
28
25
|
|
29
26
|
DEFAULT_OPTIONS = {
|
30
27
|
|
31
|
-
# To be passed to ServerEngine
|
32
|
-
server_engine: {}
|
33
|
-
|
34
28
|
}
|
35
29
|
|
36
30
|
def initialize(options = {}, context = Context.new)
|
@@ -60,7 +54,7 @@ module Startback
|
|
60
54
|
end
|
61
55
|
|
62
56
|
def bus
|
63
|
-
::Startback::Event::Bus.new
|
57
|
+
@bus ||= ::Startback::Event::Bus.new
|
64
58
|
end
|
65
59
|
|
66
60
|
def connect
|
@@ -68,20 +62,12 @@ module Startback
|
|
68
62
|
bus.connect
|
69
63
|
end
|
70
64
|
|
71
|
-
def run(options = {})
|
72
|
-
connect
|
73
|
-
|
74
|
-
log(:info, self, "Running agents and server engine!")
|
75
|
-
create_agents
|
76
|
-
Runner.new(self, options[:server_engine] || {}).run
|
77
|
-
end
|
78
|
-
|
79
65
|
def create_agents
|
80
66
|
return unless parent = self.class.auto_create_agents
|
81
67
|
|
82
68
|
ObjectSpace
|
83
69
|
.each_object(Class)
|
84
|
-
.select { |klass| klass
|
70
|
+
.select { |klass| klass <= parent }
|
85
71
|
.each { |klass| klass.new(self) }
|
86
72
|
end
|
87
73
|
|
@@ -89,88 +75,20 @@ module Startback
|
|
89
75
|
Event.json(event_data, context)
|
90
76
|
end
|
91
77
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
worker_type: 'process',
|
97
|
-
workers: 1
|
98
|
-
}
|
99
|
-
|
100
|
-
def initialize(engine, options = {})
|
101
|
-
raise ArgumentError if engine.nil?
|
102
|
-
|
103
|
-
@engine = engine
|
104
|
-
@options = DEFAULT_SERVER_ENGINE_OPTIONS.merge(options)
|
105
|
-
require 'serverengine'
|
106
|
-
end
|
107
|
-
attr_reader :engine, :options
|
108
|
-
|
109
|
-
def run(options = {})
|
110
|
-
health = self.class.build_health_check(engine)
|
111
|
-
worker = self.class.build_worker(engine, health)
|
112
|
-
se = ServerEngine.create(nil, worker, options)
|
113
|
-
se.run
|
114
|
-
se
|
115
|
-
end
|
116
|
-
|
117
|
-
class << self
|
118
|
-
def run(*args, &bl)
|
119
|
-
new.run(*args, &bl)
|
120
|
-
end
|
78
|
+
def rack_app
|
79
|
+
engine = self
|
80
|
+
Rack::Builder.new do
|
81
|
+
use Startback::Web::CatchAll
|
121
82
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
}
|
128
|
-
run(health)
|
129
|
-
end
|
130
|
-
end
|
83
|
+
map '/health-check' do
|
84
|
+
health = Startback::Web::HealthCheck.new {
|
85
|
+
engine.on_health_check
|
86
|
+
}
|
87
|
+
run(health)
|
131
88
|
end
|
89
|
+
end
|
90
|
+
end
|
132
91
|
|
133
|
-
def build_worker(engine, health)
|
134
|
-
Module.new do
|
135
|
-
include Support::Env
|
136
|
-
|
137
|
-
def initialize
|
138
|
-
@stop_flag = ServerEngine::BlockingFlag.new
|
139
|
-
end
|
140
|
-
|
141
|
-
define_method(:health) do
|
142
|
-
health
|
143
|
-
end
|
144
|
-
|
145
|
-
define_method(:engine) do
|
146
|
-
engine
|
147
|
-
end
|
148
|
-
|
149
|
-
def run
|
150
|
-
ran = false
|
151
|
-
until @stop_flag.set?
|
152
|
-
if ran
|
153
|
-
engine.send(:log, :warn, engine, "Restarting internal loop")
|
154
|
-
else
|
155
|
-
engine.send(:log, :info, engine, "Starting internal loop")
|
156
|
-
end
|
157
|
-
Rack::Handler::WEBrick.run(health, {
|
158
|
-
:Port => env('STARTBACK_ENGINE_PORT', '3000').to_i,
|
159
|
-
:Host => env('STARTBACK_ENGINE_LISTEN', '0.0.0.0')
|
160
|
-
})
|
161
|
-
ran = true
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def stop
|
166
|
-
engine.send(:log, :info, engine, "Stopping internal loop")
|
167
|
-
@stop_flag.set!
|
168
|
-
Rack::Handler::WEBrick.shutdown
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end # class << self
|
173
|
-
end # class Runner
|
174
92
|
end # class Engine
|
175
93
|
end # class Event
|
176
94
|
end # module Startback
|
data/lib/startback/event.rb
CHANGED
data/lib/startback/operation.rb
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
module Startback
|
2
|
+
module Support
|
3
|
+
module DataObject
|
4
|
+
|
5
|
+
def initialize(data = {})
|
6
|
+
@_data = data.dup.freeze
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_writer :_data
|
10
|
+
protected :_data=
|
11
|
+
|
12
|
+
def method_missing(name, *args, &bl)
|
13
|
+
return super unless args.empty? && bl.nil?
|
14
|
+
return super unless pair = _data_key_for(name)
|
15
|
+
|
16
|
+
pair.last ? !!@_data[pair.first] : @_data[pair.first]
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](name)
|
20
|
+
return nil unless pair = _data_key_for(name, false, false)
|
21
|
+
|
22
|
+
@_data[pair.first]
|
23
|
+
end
|
24
|
+
|
25
|
+
def respond_to?(name)
|
26
|
+
super || !_data_key_for(name).nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_data
|
30
|
+
@_data
|
31
|
+
end
|
32
|
+
alias :to_h :to_data
|
33
|
+
|
34
|
+
def to_json(*args, &bl)
|
35
|
+
to_data.to_json(*args, &bl)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def _data_key_for(key, try_camelize = _data_allow_camelize, try_query = _data_allow_query)
|
41
|
+
if @_data.key?(key)
|
42
|
+
[key, false]
|
43
|
+
elsif @_data.key?(key.to_s)
|
44
|
+
[key.to_s, false]
|
45
|
+
elsif key.is_a?(String) && @_data.key?(key.to_sym)
|
46
|
+
[key.to_sym, false]
|
47
|
+
elsif try_camelize
|
48
|
+
cam = key.to_s.gsub(/_([a-z])/){ $1.upcase }.to_sym
|
49
|
+
_data_key_for(cam, false, true)
|
50
|
+
elsif try_query && key.to_s =~ /\?$/
|
51
|
+
got = _data_key_for(key[0...-1].to_sym, false, false)
|
52
|
+
got ? [got.first, true] : _data_key_not_found(key)
|
53
|
+
else
|
54
|
+
_data_key_not_found(key)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def _data_allow_camelize
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def _data_allow_query
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
def _data_key_not_found(key)
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
end # module DataObject
|
70
|
+
end # module Support
|
71
|
+
end # module Startback
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Startback
|
2
|
+
module Support
|
3
|
+
class World
|
4
|
+
include DataObject
|
5
|
+
|
6
|
+
attr_accessor :_factory
|
7
|
+
protected :_factory=
|
8
|
+
|
9
|
+
def factory(who, &block)
|
10
|
+
dup.tap do |x|
|
11
|
+
x._factory = (self._factory || {}).merge(who => block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :_scope
|
16
|
+
protected :_scope=
|
17
|
+
|
18
|
+
def with_scope(scope)
|
19
|
+
dup.tap do |x|
|
20
|
+
x._scope = scope
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def with(hash)
|
25
|
+
dup.tap do |x|
|
26
|
+
x._data = to_data.merge(hash)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def _data_allow_camelize
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
def _data_allow_query
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def _data_key_not_found(key)
|
41
|
+
raise Startback::Error, "Scope must be defined" unless s = _scope
|
42
|
+
|
43
|
+
block = (_factory || {})[key]
|
44
|
+
if block
|
45
|
+
factored = s.instance_exec(&block)
|
46
|
+
@_data = @_data.dup.merge(key => factored).freeze
|
47
|
+
[key, false]
|
48
|
+
else
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end # class World
|
53
|
+
end # module Support
|
54
|
+
end # module Startback
|
data/lib/startback/support.rb
CHANGED
data/lib/startback/version.rb
CHANGED
data/lib/startback.rb
CHANGED
@@ -32,8 +32,10 @@ module Startback
|
|
32
32
|
require_relative 'startback/ext'
|
33
33
|
require_relative 'startback/errors'
|
34
34
|
require_relative 'startback/support'
|
35
|
+
require_relative 'startback/model'
|
35
36
|
require_relative 'startback/context'
|
36
37
|
require_relative 'startback/operation'
|
38
|
+
require_relative 'startback/services'
|
37
39
|
|
38
40
|
# Logger instance to use for the application
|
39
41
|
LOGGER = ::Startback::Support::Logger.new
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
1
|
require 'startback'
|
3
2
|
require 'startback/event'
|
4
3
|
require 'startback/support/fake_logger'
|
5
4
|
require 'rack/test'
|
5
|
+
require 'ostruct'
|
6
6
|
|
7
7
|
module SpecHelpers
|
8
8
|
end
|
@@ -12,23 +12,35 @@ RSpec.configure do |c|
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class SubContext < Startback::Context
|
15
|
+
|
15
16
|
attr_accessor :foo
|
17
|
+
|
16
18
|
h_factory do |c,h|
|
17
19
|
c.foo = h["foo"]
|
18
20
|
end
|
21
|
+
|
19
22
|
h_dump do |h|
|
20
23
|
h.merge!("foo" => foo)
|
21
24
|
end
|
25
|
+
|
26
|
+
world(:partner) do
|
27
|
+
Object.new
|
28
|
+
end
|
29
|
+
|
22
30
|
end
|
23
31
|
|
24
32
|
class SubContext
|
33
|
+
|
25
34
|
attr_accessor :bar
|
35
|
+
|
26
36
|
h_factory do |c,h|
|
27
37
|
c.bar = h["bar"]
|
28
38
|
end
|
39
|
+
|
29
40
|
h_dump do |h|
|
30
41
|
h.merge!("bar" => bar)
|
31
42
|
end
|
43
|
+
|
32
44
|
end
|
33
45
|
|
34
46
|
class User
|
@@ -8,8 +8,7 @@ module Startback
|
|
8
8
|
context.foo = ['hello']
|
9
9
|
|
10
10
|
forked = context.fork
|
11
|
-
|
12
|
-
expect(fork).not_to be(context)
|
11
|
+
expect(forked).not_to be(context)
|
13
12
|
expect(forked.foo).to eql(['hello'])
|
14
13
|
expect(forked.foo).to be(context.foo)
|
15
14
|
end
|
@@ -19,7 +18,7 @@ module Startback
|
|
19
18
|
|
20
19
|
seen = false
|
21
20
|
context.fork({ 'foo' => 'hello' }) do |forked|
|
22
|
-
expect(
|
21
|
+
expect(forked).not_to be(context)
|
23
22
|
expect(forked.foo).to eql('hello')
|
24
23
|
seen = true
|
25
24
|
end
|
@@ -30,7 +29,7 @@ module Startback
|
|
30
29
|
context = SubContext.new
|
31
30
|
|
32
31
|
forked = context.fork({ 'foo' => 'hello' })
|
33
|
-
expect(
|
32
|
+
expect(forked).not_to be(context)
|
34
33
|
expect(forked.foo).to eql('hello')
|
35
34
|
end
|
36
35
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Startback
|
4
|
+
describe Context, "with_world" do
|
5
|
+
|
6
|
+
let(:who) do
|
7
|
+
Object.new
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:context) do
|
11
|
+
SubContext.new.with_world(hello: who)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'works as expected' do
|
15
|
+
got = context.world.hello
|
16
|
+
expect(got).to be(who)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Startback
|
4
|
+
describe Context, "world" do
|
5
|
+
|
6
|
+
let(:context) do
|
7
|
+
SubContext.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'works as expected' do
|
11
|
+
got = context.world.partner
|
12
|
+
expect(got).not_to be_nil
|
13
|
+
expect(context.world.partner).to be(got)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Startback
|
4
|
+
module Support
|
5
|
+
describe DataObject do
|
6
|
+
|
7
|
+
class FooDataObject
|
8
|
+
include DataObject
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:data) do
|
12
|
+
{
|
13
|
+
:foo => 'bar',
|
14
|
+
'bar' => 'baz'
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
subject do
|
19
|
+
FooDataObject.new(data)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'lets create an instance with providing data' do
|
23
|
+
expect(subject).to be_a(FooDataObject)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'lets get the data back' do
|
27
|
+
expect(subject.to_data).to eql(data)
|
28
|
+
expect(subject.to_data).not_to be(data)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'lets to_json it' do
|
32
|
+
expect(subject.to_json).to eql(%Q{{"foo":"bar","bar":"baz"}})
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "data helpers" do
|
36
|
+
it 'lets access data through methods' do
|
37
|
+
expect(subject.foo).to eql('bar')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'is indifferent to symbol vs. string' do
|
41
|
+
expect(subject.bar).to eql('baz')
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'is indifferent to camel casing' do
|
45
|
+
expect(subject.bar).to eql('baz')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'raises a NoMethodError when not known' do
|
49
|
+
expect {
|
50
|
+
subject.no_such_one
|
51
|
+
}.to raise_error(NoMethodError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'implements respond_to? correctly' do
|
55
|
+
expect(subject.respond_to?(:foo)).to eql(true)
|
56
|
+
expect(subject.respond_to?(:bar)).to eql(true)
|
57
|
+
expect(subject.respond_to?(:no_such_one)).to eql(false)
|
58
|
+
end
|
59
|
+
end # data helpers
|
60
|
+
|
61
|
+
describe "? helpers" do
|
62
|
+
let(:data) do
|
63
|
+
{
|
64
|
+
'some' => 'thing',
|
65
|
+
'ready' => false,
|
66
|
+
'unready' => true,
|
67
|
+
'nothing' => nil
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'works as expected' do
|
72
|
+
expect(subject.some?).to eql(true)
|
73
|
+
expect(subject.ready?).to eql(false)
|
74
|
+
expect(subject.unready?).to eql(true)
|
75
|
+
expect(subject.nothing?).to eql(false)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'implements respond_to? correctly' do
|
79
|
+
expect(subject.respond_to?(:some?)).to eql(true)
|
80
|
+
expect(subject.respond_to?(:ready?)).to eql(true)
|
81
|
+
expect(subject.respond_to?(:unready?)).to eql(true)
|
82
|
+
expect(subject.respond_to?(:nothing?)).to eql(true)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'stays conservative' do
|
86
|
+
expect {
|
87
|
+
subject.no_such_one?
|
88
|
+
}.to raise_error(NoMethodError)
|
89
|
+
expect(subject.respond_to?(:no_such_one?)).to eql(false)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "case helpers" do
|
94
|
+
let(:data) do
|
95
|
+
{
|
96
|
+
'camelCase' => 'snake_case'
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'lets use camelCase' do
|
101
|
+
expect(subject.camelCase).to eql('snake_case')
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'lets use camel_case' do
|
105
|
+
expect(subject.camel_case).to eql('snake_case')
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'implements respond_to? correctly' do
|
109
|
+
expect(subject.respond_to?(:camelCase)).to eql(true)
|
110
|
+
expect(subject.respond_to?(:camel_case)).to eql(true)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'is compatible with ? helpers' do
|
114
|
+
expect(subject.camelCase?).to eql(true)
|
115
|
+
expect(subject.camel_case?).to eql(true)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'stays conservative' do
|
119
|
+
expect {
|
120
|
+
subject.no_such_one
|
121
|
+
}.to raise_error(NoMethodError)
|
122
|
+
expect(subject.respond_to?(:no_such_one)).to eql(false)
|
123
|
+
expect(subject.respond_to?(:no_such_one?)).to eql(false)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '[]' do
|
128
|
+
let(:data) do
|
129
|
+
{
|
130
|
+
:foo => 'bar',
|
131
|
+
'bar' => 'baz',
|
132
|
+
'camelCase' => 'snake_case'
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'lets access data' do
|
137
|
+
expect(subject[:foo]).to eql('bar')
|
138
|
+
expect(subject['bar']).to eql('baz')
|
139
|
+
expect(subject['camelCase']).to eql('snake_case')
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'uses indifferent access' do
|
143
|
+
expect(subject['foo']).to eql('bar')
|
144
|
+
expect(subject[:bar]).to eql('baz')
|
145
|
+
expect(subject[:camelCase]).to eql('snake_case')
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'has no other magic and returns nil in all other cases' do
|
149
|
+
expect(subject[:foo?]).to be_nil
|
150
|
+
expect(subject[:camel_case]).to be_nil
|
151
|
+
expect(subject[:camel_case?]).to be_nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Startback
|
4
|
+
module Support
|
5
|
+
describe World do
|
6
|
+
|
7
|
+
let(:world) do
|
8
|
+
World.new
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'with' do
|
12
|
+
subject do
|
13
|
+
world.with(foo: :bar, bar: :baz)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns a new world instance' do
|
17
|
+
expect(subject).to be_a(World)
|
18
|
+
expect(subject).not_to be(world)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'gives access to those variables' do
|
22
|
+
expect(subject.foo).to eql(:bar)
|
23
|
+
expect(subject[:bar]).to eql(:baz)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'dup' do
|
28
|
+
let(:world) do
|
29
|
+
World.new(foo: :bar)
|
30
|
+
end
|
31
|
+
|
32
|
+
subject do
|
33
|
+
world.dup
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns another instance' do
|
37
|
+
expect(subject).to be_a(World)
|
38
|
+
expect(subject).not_to be(world)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'keeps variables' do
|
42
|
+
expect(subject.foo).to eql(:bar)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'class factory' do
|
47
|
+
subject do
|
48
|
+
world.factory(:foo) do
|
49
|
+
hello
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def hello
|
54
|
+
OpenStruct.new(bar: 12)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns a world instance' do
|
58
|
+
expect(subject).to be_a(World)
|
59
|
+
expect(subject).not_to be(world)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'installs the factory' do
|
63
|
+
bound = subject.with_scope(self)
|
64
|
+
got = bound.foo
|
65
|
+
expect(got).to be_a(OpenStruct)
|
66
|
+
expect(got.bar).to eql(12)
|
67
|
+
expect(bound.foo).to be(got)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/tasks/test.rake
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rspec/core/rake_task'
|
2
|
+
require 'path'
|
2
3
|
|
3
4
|
namespace :test do
|
4
5
|
|
@@ -8,14 +9,6 @@ namespace :test do
|
|
8
9
|
t.rspec_opts = %{-Ilib -Ispec --color --backtrace --format progress --format RspecJunitFormatter --out spec/rspec-unit.xml}
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
-
task :example do
|
13
|
-
Bundler.with_original_env do
|
14
|
-
system("cd example && bundle exec rake")
|
15
|
-
abort("Example tests failed") unless $?.exitstatus == 0
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
task :all => [:unit, :example]
|
12
|
+
task :all => [:unit]
|
20
13
|
end
|
21
14
|
task :test => :'test:all'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: startback
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -270,20 +270,20 @@ dependencies:
|
|
270
270
|
requirements:
|
271
271
|
- - ">="
|
272
272
|
- !ruby/object:Gem::Version
|
273
|
-
version: 0.
|
273
|
+
version: 0.20.0
|
274
274
|
- - "<"
|
275
275
|
- !ruby/object:Gem::Version
|
276
|
-
version: 0.
|
276
|
+
version: 0.21.0
|
277
277
|
type: :runtime
|
278
278
|
prerelease: false
|
279
279
|
version_requirements: !ruby/object:Gem::Requirement
|
280
280
|
requirements:
|
281
281
|
- - ">="
|
282
282
|
- !ruby/object:Gem::Version
|
283
|
-
version: 0.
|
283
|
+
version: 0.20.0
|
284
284
|
- - "<"
|
285
285
|
- !ruby/object:Gem::Version
|
286
|
-
version: 0.
|
286
|
+
version: 0.21.0
|
287
287
|
- !ruby/object:Gem::Dependency
|
288
288
|
name: tzinfo
|
289
289
|
requirement: !ruby/object:Gem::Requirement
|
@@ -389,6 +389,7 @@ files:
|
|
389
389
|
- lib/startback/caching/no_store.rb
|
390
390
|
- lib/startback/caching/store.rb
|
391
391
|
- lib/startback/context.rb
|
392
|
+
- lib/startback/context/h_factory.rb
|
392
393
|
- lib/startback/context/middleware.rb
|
393
394
|
- lib/startback/errors.rb
|
394
395
|
- lib/startback/event.rb
|
@@ -405,10 +406,13 @@ files:
|
|
405
406
|
- lib/startback/ext.rb
|
406
407
|
- lib/startback/ext/date_time.rb
|
407
408
|
- lib/startback/ext/time.rb
|
409
|
+
- lib/startback/model.rb
|
408
410
|
- lib/startback/operation.rb
|
409
411
|
- lib/startback/operation/error_operation.rb
|
410
412
|
- lib/startback/operation/multi_operation.rb
|
413
|
+
- lib/startback/services.rb
|
411
414
|
- lib/startback/support.rb
|
415
|
+
- lib/startback/support/data_object.rb
|
412
416
|
- lib/startback/support/env.rb
|
413
417
|
- lib/startback/support/fake_logger.rb
|
414
418
|
- lib/startback/support/hooks.rb
|
@@ -418,6 +422,7 @@ files:
|
|
418
422
|
- lib/startback/support/robustness.rb
|
419
423
|
- lib/startback/support/transaction_manager.rb
|
420
424
|
- lib/startback/support/transaction_policy.rb
|
425
|
+
- lib/startback/support/world.rb
|
421
426
|
- lib/startback/version.rb
|
422
427
|
- lib/startback/web/api.rb
|
423
428
|
- lib/startback/web/auto_caching.rb
|
@@ -439,15 +444,19 @@ files:
|
|
439
444
|
- spec/unit/context/test_fork.rb
|
440
445
|
- spec/unit/context/test_h_factory.rb
|
441
446
|
- spec/unit/context/test_middleware.rb
|
447
|
+
- spec/unit/context/test_with_world.rb
|
448
|
+
- spec/unit/context/test_world.rb
|
442
449
|
- spec/unit/event/bus/memory/test_async.rb
|
443
450
|
- spec/unit/event/bus/memory/test_sync.rb
|
444
451
|
- spec/unit/support/hooks/test_after_hook.rb
|
445
452
|
- spec/unit/support/hooks/test_before_hook.rb
|
446
453
|
- spec/unit/support/operation_runner/test_around_run.rb
|
447
454
|
- spec/unit/support/operation_runner/test_before_after_call.rb
|
455
|
+
- spec/unit/support/test_data_object.rb
|
448
456
|
- spec/unit/support/test_env.rb
|
449
457
|
- spec/unit/support/test_robusteness.rb
|
450
458
|
- spec/unit/support/test_transaction_manager.rb
|
459
|
+
- spec/unit/support/test_world.rb
|
451
460
|
- spec/unit/test_event.rb
|
452
461
|
- spec/unit/test_operation.rb
|
453
462
|
- spec/unit/test_support.rb
|
@@ -461,7 +470,7 @@ files:
|
|
461
470
|
- spec/unit/web/test_healthcheck.rb
|
462
471
|
- spec/unit/web/test_magic_assets.rb
|
463
472
|
- tasks/test.rake
|
464
|
-
homepage:
|
473
|
+
homepage: https://www.enspirit.be
|
465
474
|
licenses:
|
466
475
|
- MIT
|
467
476
|
metadata: {}
|
@@ -480,7 +489,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
480
489
|
- !ruby/object:Gem::Version
|
481
490
|
version: '0'
|
482
491
|
requirements: []
|
483
|
-
rubygems_version: 3.
|
492
|
+
rubygems_version: 3.1.2
|
484
493
|
signing_key:
|
485
494
|
specification_version: 4
|
486
495
|
summary: Got Your Ruby Back
|