startback 0.12.3 → 0.14.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
  SHA256:
3
- metadata.gz: 402d175b50a47cda7b683e91613fa0b15405ba0415b1d4b27c765f087717951e
4
- data.tar.gz: 6b926b4b805ca0623cd66f37a80802d0eb9a41a44707be1952d8cb4f328314ee
3
+ metadata.gz: '0871c178ad572a32e21b8ff867b9f24264751ff0e37feb3687086619fe768032'
4
+ data.tar.gz: 2cbcfea7ede9b7773477498e251ac9290e6874baa1e0f0e78e2e8fba2e0e1c6b
5
5
  SHA512:
6
- metadata.gz: 7c5093716de177a26401e82cb90d5b596696b11ff3b5ce390b7deae7eba67f3e939b8fa1c1594fea3ad866e7d05d364fbc6243428b8cf378573ddbe6843052c3
7
- data.tar.gz: 24ec0a98d2374cb78130df5358909a4715ee7f7a5e4ec6685a136bc67b03ea8eaff26b0d2f6a52cbd19219145d034a6b95c8147dbe11aa64549a195ff0f81990
6
+ metadata.gz: 2b4e6bf66f0bceb9a3ef13bc13b25b6dcb1bca5de20c4962ab704e2c68501361fef2ae63e7ca2b562f239926d6205544dc16c4deccc3757d1882e18c7a46d040
7
+ data.tar.gz: 3a66a3854053753e4e14afb76c948c792ba15d45b20ceb9d506ddd14401ded9fbdb3cff493ec7b46ed502756943578f86c39292f1d09462406fc80c9e8f5024a
@@ -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
@@ -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
- # Implementation of the `h` information contract
52
- class << self
52
+ require_relative 'context/h_factory'
53
+ extend(Context::HFactory)
53
54
 
54
- def h(hash)
55
- h_factor!(self.new, hash)
56
- end
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
- def h_factory(&factory)
70
- h_factories << factory
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
- def h_dump!(context, hash = {})
76
- h_dumpers.each do |d|
77
- context.instance_exec(hash, &d)
78
- end
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
- def h_dumpers
83
- @h_dumpers ||= []
84
- end
73
+ def world
74
+ @_world ||= self.class.factor_world(self)
75
+ end
85
76
 
86
- def h_dump(&dumper)
87
- h_dumpers << dumper
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).
@@ -76,7 +76,7 @@ module Startback
76
76
  end
77
77
 
78
78
  def operation_world(op)
79
- super(op).merge(context: ctx)
79
+ super(op).merge(context: context)
80
80
  end
81
81
 
82
82
  end # class Agent
@@ -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, and the possibility for the
10
- # the listening part to start an infinite loop (ServerEngine).
8
+ # and listeners can connect.
11
9
  #
12
- # The Engine automatically runs a Webrick small webapp
13
- # with a /healthcheck webservice. The class can be extended
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 < parent }
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
- class Runner
93
-
94
- DEFAULT_SERVER_ENGINE_OPTIONS = {
95
- daemonize: false,
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
- def build_health_check(engine)
123
- Rack::Builder.new do
124
- map '/health-check' do
125
- health = Startback::Web::HealthCheck.new {
126
- engine.on_health_check
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
@@ -0,0 +1,6 @@
1
+ module Startback
2
+ class Model
3
+ include Support::DataObject
4
+
5
+ end # class Model
6
+ end # module Startback
@@ -37,6 +37,11 @@ module Startback
37
37
  attr_accessor :world
38
38
  protected :world=
39
39
 
40
+ def initialize(input = {})
41
+ @input = input
42
+ end
43
+ attr_reader :input
44
+
40
45
  def bind(world)
41
46
  return self unless world
42
47
  self.world = world
@@ -0,0 +1,11 @@
1
+ module Startback
2
+ class Services
3
+ include Startback::Errors
4
+
5
+ def initialize(context)
6
+ @context = context
7
+ end
8
+ attr_reader :context
9
+
10
+ end # class Services
11
+ end # module Startback
@@ -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
@@ -22,3 +22,5 @@ require_relative 'support/hooks'
22
22
  require_relative 'support/operation_runner'
23
23
  require_relative 'support/transaction_policy'
24
24
  require_relative 'support/transaction_manager'
25
+ require_relative 'support/data_object'
26
+ require_relative 'support/world'
@@ -1,8 +1,8 @@
1
1
  module Startback
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 12
5
- TINY = 3
4
+ MINOR = 14
5
+ TINY = 1
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
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
- puts "Forked: #{forked.inspect}"
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(fork).not_to be(context)
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(fork).not_to be(context)
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
- desc "Run the tests in the examples folder"
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.12.3
4
+ version: 0.14.1
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-05-25 00:00:00.000000000 Z
11
+ date: 2022-06-08 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.19.0
273
+ version: 0.20.0
274
274
  - - "<"
275
275
  - !ruby/object:Gem::Version
276
- version: 0.20.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.19.0
283
+ version: 0.20.0
284
284
  - - "<"
285
285
  - !ruby/object:Gem::Version
286
- version: 0.20.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: http://www.enspirit.be
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.3.7
492
+ rubygems_version: 3.1.2
484
493
  signing_key:
485
494
  specification_version: 4
486
495
  summary: Got Your Ruby Back