startback 0.12.1 → 0.13.0

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: '085ac55f8fc68a8b8806570359e68ae9cba48a0c0cef83645bfb9f7133fb38ce'
4
- data.tar.gz: 231685b5e7c8c53a3cb086bbdc8ef6728132a942a47b59e6ac5c1ca6560b2725
3
+ metadata.gz: 5b7ccc8dd2081ba0dffda6092a2dbb2a345b01e6b7231aee41aa506e85949a4a
4
+ data.tar.gz: c53f396f235226bbbfd336c872a5e1334708e1dcc6ca62d456d7b969bf7baad2
5
5
  SHA512:
6
- metadata.gz: 3c12830f86d5e0a067b801ebc752c894d7abec27c9745bb8eb307eee010a049275b49f3bfa1f55a1b7bf168c9fc3222b7039f6dc243f96c5268d369b625eabb3
7
- data.tar.gz: dedb51337c356d9208ea727155c978dd6e937c2d8016189c17c606820975e81d1ede4e004a22878e8060dd58cd84280a4119f1a1996dae5c26bbdfc660009029
6
+ metadata.gz: c5c4b8ecc4045efd18f206217ddc201c869929e1951e981bf07fae0a9ff710d60d00b444f871bac7096a8ee48f7b05f0d95498f58c3d737be5a5b08e3a626707
7
+ data.tar.gz: d193c22d134a0f57403433a6e4f0279d74ca17aaf7d99278664a86c5a3d2118d7a926bc7a95957ad2e4bbe90a8fafb82f549a938e73d3996204aa98f0b19c4fc
@@ -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).
@@ -112,6 +103,13 @@ module Startback
112
103
  to_h.to_json(*args, &bl)
113
104
  end
114
105
 
106
+ def fork(h = nil)
107
+ dup.tap{|duped|
108
+ self.class.h_factor!(duped, h) if h
109
+ yield(duped) if block_given?
110
+ }
111
+ end
112
+
115
113
  def dup
116
114
  super.tap{|c|
117
115
  c.send(:clean_factored!)
@@ -16,9 +16,12 @@ module Startback
16
16
 
17
17
  def initialize(engine)
18
18
  @engine = engine
19
+ @context = nil
19
20
  install_listeners
20
21
  end
21
22
  attr_reader :engine
23
+ attr_accessor :context
24
+ protected :context=
22
25
 
23
26
  protected
24
27
 
@@ -40,7 +43,7 @@ module Startback
40
43
  def async(exchange, queue)
41
44
  bus.async.listen(exchange, queue) do |event_data|
42
45
  event = engine.factor_event(event_data)
43
- dup.call(event)
46
+ with_context(event.context).call(event)
44
47
  end
45
48
  end
46
49
 
@@ -50,7 +53,7 @@ module Startback
50
53
  def sync(exchange, queue)
51
54
  bus.listen(exchange, queue) do |event_data|
52
55
  event = engine.factor_event(event_data)
53
- dup.call(event)
56
+ with_context(event.context).call(event)
54
57
  end
55
58
  end
56
59
 
@@ -68,6 +71,14 @@ module Startback
68
71
  raise NotImplementedError
69
72
  end
70
73
 
74
+ def with_context(context)
75
+ dup.tap{|a| a.send(:context=, context) }
76
+ end
77
+
78
+ def operation_world(op)
79
+ super(op).merge(context: context)
80
+ end
81
+
71
82
  end # class Agent
72
83
  end # class Event
73
84
  end # module Starback
@@ -86,7 +86,7 @@ module Startback
86
86
  end
87
87
 
88
88
  def factor_event(event_data)
89
- Event.json(event_data, context.dup)
89
+ Event.json(event_data, context)
90
90
  end
91
91
 
92
92
  class Runner
@@ -21,8 +21,11 @@ module Startback
21
21
  attr_reader :context, :type, :data
22
22
 
23
23
  def self.json(src, context)
24
+ return src if src.is_a?(Event)
25
+
24
26
  parsed = JSON.parse(src)
25
27
  klass = Kernel.const_get(parsed['type'])
28
+ context = context.fork(parsed['context']) if context
26
29
  klass.new(parsed['type'], parsed['data'], context)
27
30
  end
28
31
 
@@ -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 = 1
4
+ MINOR = 13
5
+ TINY = 0
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
@@ -11,6 +11,38 @@ RSpec.configure do |c|
11
11
  c.include SpecHelpers
12
12
  end
13
13
 
14
+ class SubContext < Startback::Context
15
+
16
+ attr_accessor :foo
17
+
18
+ h_factory do |c,h|
19
+ c.foo = h["foo"]
20
+ end
21
+
22
+ h_dump do |h|
23
+ h.merge!("foo" => foo)
24
+ end
25
+
26
+ world(:partner) do
27
+ Object.new
28
+ end
29
+
30
+ end
31
+
32
+ class SubContext
33
+
34
+ attr_accessor :bar
35
+
36
+ h_factory do |c,h|
37
+ c.bar = h["bar"]
38
+ end
39
+
40
+ h_dump do |h|
41
+ h.merge!("bar" => bar)
42
+ end
43
+
44
+ end
45
+
14
46
  class User
15
47
  class Changed < Startback::Event
16
48
  end
@@ -3,12 +3,8 @@ require 'spec_helper'
3
3
  module Startback
4
4
  describe Context, "dup" do
5
5
 
6
- class Subcontext < Context
7
- attr_accessor :foo
8
- end
9
-
10
6
  let(:context) {
11
- Subcontext.new.tap{|s| s.foo = "bar" }
7
+ SubContext.new.tap{|s| s.foo = "bar" }
12
8
  }
13
9
 
14
10
  class ContextRelatedAbstraction
@@ -27,7 +23,7 @@ module Startback
27
23
  expect(x).not_to be(context)
28
24
  }
29
25
  expect(seen).to be(got)
30
- expect(got).to be_a(Subcontext)
26
+ expect(got).to be_a(SubContext)
31
27
  expect(got).not_to be(context)
32
28
  expect(got.foo).to eql("bar")
33
29
  end
@@ -43,4 +39,4 @@ module Startback
43
39
  end
44
40
 
45
41
  end
46
- end
42
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ describe Context, "fork" do
5
+
6
+ it 'is a simple dup without args' do
7
+ context = SubContext.new
8
+ context.foo = ['hello']
9
+
10
+ forked = context.fork
11
+ expect(forked).not_to be(context)
12
+ expect(forked.foo).to eql(['hello'])
13
+ expect(forked.foo).to be(context.foo)
14
+ end
15
+
16
+ it 'yields the context if a block is provided' do
17
+ context = SubContext.new
18
+
19
+ seen = false
20
+ context.fork({ 'foo' => 'hello' }) do |forked|
21
+ expect(forked).not_to be(context)
22
+ expect(forked.foo).to eql('hello')
23
+ seen = true
24
+ end
25
+ expect(seen).to eql(true)
26
+ end
27
+
28
+ it 'uses the factory on the hash provided' do
29
+ context = SubContext.new
30
+
31
+ forked = context.fork({ 'foo' => 'hello' })
32
+ expect(forked).not_to be(context)
33
+ expect(forked.foo).to eql('hello')
34
+ end
35
+
36
+ end
37
+ end
@@ -7,26 +7,6 @@ module Startback
7
7
  expect(Context.new.to_json).to eql("{}")
8
8
  end
9
9
 
10
- class SubContext < Context
11
- attr_accessor :foo
12
- h_factory do |c,h|
13
- c.foo = h["foo"]
14
- end
15
- h_dump do |h|
16
- h.merge!("foo" => foo)
17
- end
18
- end
19
-
20
- class SubContext
21
- attr_accessor :bar
22
- h_factory do |c,h|
23
- c.bar = h["bar"]
24
- end
25
- h_dump do |h|
26
- h.merge!("bar" => bar)
27
- end
28
- end
29
-
30
10
  it 'allows installing factories' do
31
11
  expect(Context.h_factories).to be_empty
32
12
  expect(SubContext.h_factories.size).to eql(2)
@@ -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
@@ -50,8 +50,11 @@ module Startback
50
50
  end
51
51
 
52
52
  it 'accepts an explicit context as second argument' do
53
- evt = Event.json(JSON_SRC, 12)
54
- expect(evt.context).to eql(12)
53
+ c = SubContext.new.tap{|x| x.foo = 'hello' }
54
+ evt = Event.json(JSON_SRC, c)
55
+ expect(evt.context).not_to be(c)
56
+ expect(evt.context).to be_a(SubContext)
57
+ expect(evt.context.foo).to eql('hello')
55
58
  end
56
59
  end
57
60
 
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
 
@@ -16,6 +17,21 @@ namespace :test do
16
17
  end
17
18
  end
18
19
 
19
- task :all => [:unit, :example]
20
+ contribs = (Path.dir.parent/"contrib").glob("*").map do |sub|
21
+ next unless sub.directory?
22
+ name = sub.basename.to_sym
23
+
24
+ desc "Run tests for #{sub}"
25
+ task name do
26
+ Bundler.with_original_env do
27
+ system("cd #{sub} && bundle exec rake")
28
+ abort("#{sub} tests failed") unless $?.exitstatus == 0
29
+ end
30
+ end
31
+
32
+ name
33
+ end
34
+
35
+ task :all => [:unit, :example] + contribs
20
36
  end
21
37
  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.1
4
+ version: 0.13.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-05-19 00:00:00.000000000 Z
11
+ date: 2022-05-31 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
@@ -436,17 +441,22 @@ files:
436
441
  - spec/unit/caching/test_entity_cache.rb
437
442
  - spec/unit/context/test_abstraction_factory.rb
438
443
  - spec/unit/context/test_dup.rb
444
+ - spec/unit/context/test_fork.rb
439
445
  - spec/unit/context/test_h_factory.rb
440
446
  - spec/unit/context/test_middleware.rb
447
+ - spec/unit/context/test_with_world.rb
448
+ - spec/unit/context/test_world.rb
441
449
  - spec/unit/event/bus/memory/test_async.rb
442
450
  - spec/unit/event/bus/memory/test_sync.rb
443
451
  - spec/unit/support/hooks/test_after_hook.rb
444
452
  - spec/unit/support/hooks/test_before_hook.rb
445
453
  - spec/unit/support/operation_runner/test_around_run.rb
446
454
  - spec/unit/support/operation_runner/test_before_after_call.rb
455
+ - spec/unit/support/test_data_object.rb
447
456
  - spec/unit/support/test_env.rb
448
457
  - spec/unit/support/test_robusteness.rb
449
458
  - spec/unit/support/test_transaction_manager.rb
459
+ - spec/unit/support/test_world.rb
450
460
  - spec/unit/test_event.rb
451
461
  - spec/unit/test_operation.rb
452
462
  - spec/unit/test_support.rb