scorpion-ioc 0.6.2 → 1.0.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +144 -30
- data/Gemfile +17 -13
- data/README.md +24 -69
- data/Rakefile +12 -0
- data/app/README +1 -0
- data/bin/rspec +2 -1
- data/config.ru +2 -2
- data/config/environment.rb +1 -0
- data/lib/scorpion-ioc.rb +3 -1
- data/lib/scorpion.rb +32 -45
- data/lib/scorpion/attribute.rb +14 -34
- data/lib/scorpion/attribute_set.rb +11 -13
- data/lib/scorpion/chain_hunter.rb +4 -4
- data/lib/scorpion/dependency.rb +22 -58
- data/lib/scorpion/dependency/argument_dependency.rb +4 -4
- data/lib/scorpion/dependency/builder_dependency.rb +5 -5
- data/lib/scorpion/dependency/captured_dependency.rb +4 -6
- data/lib/scorpion/dependency/class_dependency.rb +3 -17
- data/lib/scorpion/dependency/module_dependency.rb +1 -1
- data/lib/scorpion/dependency_map.rb +16 -16
- data/lib/scorpion/error.rb +12 -9
- data/lib/scorpion/hunt.rb +33 -34
- data/lib/scorpion/hunter.rb +6 -6
- data/lib/scorpion/locale/en.yml +2 -2
- data/lib/scorpion/method.rb +11 -1
- data/lib/scorpion/object.rb +16 -31
- data/lib/scorpion/rack.rb +1 -1
- data/lib/scorpion/rack/middleware.rb +2 -1
- data/lib/scorpion/rails.rb +6 -6
- data/lib/scorpion/rails/active_record.rb +4 -4
- data/lib/scorpion/rails/active_record/association.rb +3 -3
- data/lib/scorpion/rails/active_record/relation.rb +3 -2
- data/lib/scorpion/rails/controller.rb +2 -2
- data/lib/scorpion/rails/job.rb +1 -1
- data/lib/scorpion/rails/mailer.rb +1 -1
- data/lib/scorpion/rails/nest.rb +11 -11
- data/lib/scorpion/rails/railtie.rb +2 -2
- data/lib/scorpion/rspec.rb +2 -2
- data/lib/scorpion/rspec/helper.rb +3 -3
- data/lib/scorpion/stinger.rb +19 -18
- data/lib/scorpion/version.rb +3 -3
- data/scorpion.gemspec +13 -13
- data/spec/internal/db/schema.rb +1 -1
- data/spec/lib/scorpion/attribute_set_spec.rb +4 -22
- data/spec/lib/scorpion/attribute_spec.rb +3 -8
- data/spec/lib/scorpion/chain_hunter_spec.rb +1 -1
- data/spec/lib/scorpion/dependency/argument_dependency_spec.rb +3 -7
- data/spec/lib/scorpion/dependency/builder_dependency_spec.rb +7 -7
- data/spec/lib/scorpion/dependency/module_dependency_spec.rb +3 -3
- data/spec/lib/scorpion/dependency_map_spec.rb +4 -25
- data/spec/lib/scorpion/dependency_spec.rb +18 -45
- data/spec/lib/scorpion/error_spec.rb +1 -1
- data/spec/lib/scorpion/hunt_spec.rb +16 -28
- data/spec/lib/scorpion/hunter_spec.rb +29 -21
- data/spec/lib/scorpion/object_spec.rb +20 -19
- data/spec/lib/scorpion/rack/middleware_spec.rb +4 -4
- data/spec/lib/scorpion/rack_spec.rb +1 -1
- data/spec/lib/scorpion/rails/active_record/association_spec.rb +3 -3
- data/spec/lib/scorpion/rails/active_record/model_spec.rb +3 -3
- data/spec/lib/scorpion/rails/active_record/relation_spec.rb +3 -3
- data/spec/lib/scorpion/rails/controller_spec.rb +8 -8
- data/spec/lib/scorpion/rails/job_spec.rb +1 -1
- data/spec/lib/scorpion/rspec/helper_spec.rb +11 -11
- data/spec/lib/scorpion_spec.rb +1 -1
- data/spec/spec_helper.rb +8 -10
- metadata +6 -6
- data/lib/scorpion/object_constructor.rb +0 -79
- data/spec/lib/scorpion/object_constructor_spec.rb +0 -124
data/lib/scorpion/error.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
|
-
require
|
1
|
+
require "i18n"
|
2
2
|
|
3
3
|
module Scorpion
|
4
4
|
class Error < StandardError
|
5
5
|
|
6
6
|
private
|
7
|
-
|
8
|
-
|
7
|
+
|
8
|
+
def translate( key, **args )
|
9
|
+
I18n.translate key, args.merge( scope: [:scorpion, :errors, :messages] )
|
9
10
|
end
|
11
|
+
|
10
12
|
end
|
11
13
|
|
12
14
|
class UnsuccessfulHunt < Error
|
13
15
|
attr_reader :contract
|
14
|
-
attr_reader :traits
|
15
16
|
|
16
|
-
def initialize( contract
|
17
|
+
def initialize( contract )
|
17
18
|
@contract = contract
|
18
|
-
@traits = traits
|
19
19
|
|
20
|
-
super translate( :unsuccessful_hunt, contract: contract
|
20
|
+
super translate( :unsuccessful_hunt, contract: contract )
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -36,10 +36,13 @@ module Scorpion
|
|
36
36
|
class ContractMismatchError < Error
|
37
37
|
def initialize( message_or_module = nil, initializer_attr = nil, injected_attr = nil )
|
38
38
|
if message_or_module.is_a?( Module )
|
39
|
-
super translate( :contract_mismatch, module: message_or_module,
|
39
|
+
super translate( :contract_mismatch, module: message_or_module,
|
40
|
+
name: initializer_attr.name,
|
41
|
+
from: initializer_attr.contract,
|
42
|
+
to: injected_attr.contract )
|
40
43
|
else
|
41
44
|
super ( message || translate( :contract_mismatch ) )
|
42
45
|
end
|
43
46
|
end
|
44
47
|
end
|
45
|
-
end
|
48
|
+
end
|
data/lib/scorpion/hunt.rb
CHANGED
@@ -45,17 +45,11 @@ module Scorpion
|
|
45
45
|
attr_reader :trip
|
46
46
|
private :trip
|
47
47
|
|
48
|
-
delegate [:contract, :
|
48
|
+
delegate [:contract, :arguments, :block] => :trip
|
49
49
|
|
50
50
|
# @!attribute contract
|
51
51
|
# @return [Class,Module,Symbol] contract being hunted for.
|
52
52
|
|
53
|
-
# @!attribute traits
|
54
|
-
# @return [Array<Symbol>] traits being hunted for.
|
55
|
-
|
56
|
-
# @!attribute [r] dependencies
|
57
|
-
# @return [Hash<Symbol,Dependency>] hash of dependencies to pass to initializer of {#contract} when found.
|
58
|
-
|
59
53
|
# @!attribute [r] arguments
|
60
54
|
# @return [Array<Object>] positional arguments to pass to the initializer of {#contract} when found.
|
61
55
|
|
@@ -65,22 +59,16 @@ module Scorpion
|
|
65
59
|
#
|
66
60
|
# @!endgroup Attributes
|
67
61
|
|
68
|
-
def initialize( scorpion, contract,
|
62
|
+
def initialize( scorpion, contract, *arguments, &block )
|
69
63
|
@scorpion = scorpion
|
70
64
|
@trips = []
|
71
|
-
@trip = Trip.new contract,
|
65
|
+
@trip = Trip.new contract, arguments, block
|
72
66
|
end
|
73
67
|
|
74
|
-
# Hunt for additional dependency to satisfy the main hunt's contract
|
68
|
+
# Hunt for additional dependency to satisfy the main hunt's contract.
|
75
69
|
# @see Scorpion#hunt
|
76
|
-
def fetch( contract, *arguments,
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
# Hunt for additional dependency to satisfy the main hunt's contract and traits.
|
81
|
-
# @see Scorpion#hunt
|
82
|
-
def fetch_by_traits( contract, traits, *arguments, **dependencies, &block )
|
83
|
-
push contract, traits, arguments, dependencies, block
|
70
|
+
def fetch( contract, *arguments, &block )
|
71
|
+
push contract, arguments, block
|
84
72
|
execute
|
85
73
|
ensure
|
86
74
|
pop
|
@@ -91,12 +79,13 @@ module Scorpion
|
|
91
79
|
# @return [Scorpion::Object] the injected object.
|
92
80
|
def inject( object )
|
93
81
|
trip.object = object
|
82
|
+
object.send :scorpion_hunt=, self
|
94
83
|
|
95
84
|
object.injected_attributes.each do |attr|
|
96
85
|
next if object.send "#{ attr.name }?"
|
97
86
|
next if attr.lazy?
|
98
87
|
|
99
|
-
object.send :inject_dependency, attr,
|
88
|
+
object.send :inject_dependency, attr, fetch( attr.contract )
|
100
89
|
end
|
101
90
|
|
102
91
|
object.send :on_injected
|
@@ -106,8 +95,8 @@ module Scorpion
|
|
106
95
|
|
107
96
|
# Allow the hunt to spawn objects.
|
108
97
|
# @see Scorpion#spawn
|
109
|
-
def spawn( klass, *arguments,
|
110
|
-
scorpion.spawn( self, klass, *arguments,
|
98
|
+
def spawn( klass, *arguments, &block )
|
99
|
+
scorpion.spawn( self, klass, *arguments, &block )
|
111
100
|
end
|
112
101
|
alias_method :new, :spawn
|
113
102
|
|
@@ -118,12 +107,26 @@ module Scorpion
|
|
118
107
|
end
|
119
108
|
|
120
109
|
def execute_from_trips
|
121
|
-
return if dependencies.any?
|
122
|
-
|
123
110
|
trips.each do |trip|
|
124
|
-
|
125
|
-
|
126
|
-
|
111
|
+
if resolved = execute_from_trip( trip )
|
112
|
+
return resolved
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
|
119
|
+
def execute_from_trip( trip )
|
120
|
+
return unless obj = trip.object
|
121
|
+
return obj if contract === obj
|
122
|
+
|
123
|
+
# If we have already resolved an instance of this contract in this
|
124
|
+
# hunt, then return that same object.
|
125
|
+
if obj.is_a? Scorpion::Object
|
126
|
+
obj.injected_attributes.each do |attr|
|
127
|
+
next unless attr.contract == contract
|
128
|
+
|
129
|
+
return obj.send( attr.name ) if obj.send( :"#{ attr.name }?" )
|
127
130
|
end
|
128
131
|
end
|
129
132
|
|
@@ -134,10 +137,10 @@ module Scorpion
|
|
134
137
|
scorpion.execute self
|
135
138
|
end
|
136
139
|
|
137
|
-
def push( contract,
|
140
|
+
def push( contract, arguments, block )
|
138
141
|
trips.push trip
|
139
142
|
|
140
|
-
@trip = Trip.new contract,
|
143
|
+
@trip = Trip.new contract, arguments, block
|
141
144
|
end
|
142
145
|
|
143
146
|
def pop
|
@@ -146,22 +149,18 @@ module Scorpion
|
|
146
149
|
|
147
150
|
class Trip
|
148
151
|
attr_reader :contract
|
149
|
-
attr_reader :traits
|
150
152
|
attr_reader :arguments
|
151
|
-
attr_reader :dependencies
|
152
153
|
attr_reader :block
|
153
154
|
|
154
155
|
attr_accessor :object
|
155
156
|
|
156
|
-
def initialize( contract,
|
157
|
+
def initialize( contract, arguments, block )
|
157
158
|
@contract = contract
|
158
|
-
@traits = traits
|
159
159
|
@arguments = arguments
|
160
|
-
@dependencies = dependencies
|
161
160
|
@block = block
|
162
161
|
end
|
163
162
|
end
|
164
163
|
|
165
164
|
class InitializerTrip < Trip; end
|
166
165
|
end
|
167
|
-
end
|
166
|
+
end
|
data/lib/scorpion/hunter.rb
CHANGED
@@ -33,8 +33,8 @@ module Scorpion
|
|
33
33
|
end
|
34
34
|
|
35
35
|
# Expose dependency injection definitions as top-level methods.
|
36
|
-
[:hunt_for
|
37
|
-
define_method delegate do |*args
|
36
|
+
[:hunt_for, :capture, :share].each do |delegate|
|
37
|
+
define_method delegate do |*args, &block|
|
38
38
|
prepare do |hunter|
|
39
39
|
hunter.send delegate, *args, &block
|
40
40
|
end
|
@@ -51,9 +51,9 @@ module Scorpion
|
|
51
51
|
# @see Scorpion#execute
|
52
52
|
def execute( hunt, explicit_only = false )
|
53
53
|
dependency = find_dependency( hunt )
|
54
|
-
dependency ||= Dependency.define( hunt.contract )
|
54
|
+
dependency ||= Dependency.define( hunt.contract ) unless explicit_only
|
55
55
|
|
56
|
-
unsuccessful_hunt( hunt.contract
|
56
|
+
unsuccessful_hunt( hunt.contract ) unless dependency
|
57
57
|
|
58
58
|
dependency.fetch hunt
|
59
59
|
end
|
@@ -62,7 +62,7 @@ module Scorpion
|
|
62
62
|
# @param [Hunt] hunt being resolved.
|
63
63
|
# @return [Dependency] the matching dependency if found
|
64
64
|
def find_dependency( hunt )
|
65
|
-
dependency = dependency_map.find( hunt.contract
|
65
|
+
dependency = dependency_map.find( hunt.contract )
|
66
66
|
dependency ||= parent.find_dependency( hunt ) if parent
|
67
67
|
|
68
68
|
dependency
|
@@ -83,4 +83,4 @@ module Scorpion
|
|
83
83
|
end
|
84
84
|
|
85
85
|
end
|
86
|
-
end
|
86
|
+
end
|
data/lib/scorpion/locale/en.yml
CHANGED
@@ -2,11 +2,11 @@ en:
|
|
2
2
|
scorpion:
|
3
3
|
errors:
|
4
4
|
messages:
|
5
|
-
unsuccessful_hunt: "Couldn't find a %{contract} builder
|
5
|
+
unsuccessful_hunt: "Couldn't find a %{contract} builder"
|
6
6
|
builder_required: A custom builder must be provided to resolve this dependency
|
7
7
|
arity_mismatch: The block must accept %{expected} arguments, but actually expects %{actual}
|
8
8
|
rack_missing_scorpion: Scorpion not set. Add Scorpion::Rack::Middleware before %{middleware}.
|
9
9
|
contract_mismatch: "%{module} changed the contract for `%{name}` from `%{from}` to `%{to}` but did not update `initialize` block."
|
10
10
|
warnings:
|
11
11
|
messages:
|
12
|
-
mixed_scorpions: A scorpion has already been assigned. Mixing scorpions can result in unexpected results.
|
12
|
+
mixed_scorpions: A scorpion has already been assigned. Mixing scorpions can result in unexpected results.
|
data/lib/scorpion/method.rb
CHANGED
@@ -20,5 +20,15 @@ module Scorpion
|
|
20
20
|
@scorpion = value
|
21
21
|
end
|
22
22
|
|
23
|
+
# @!attribute
|
24
|
+
# @return [Hunt] the scorpion hunt that captured the object.
|
25
|
+
def scorpion_hunt
|
26
|
+
@scorpion_hunt
|
27
|
+
end
|
28
|
+
|
29
|
+
private def scorpion_hunt=( hunt )
|
30
|
+
@scorpion_hunt = hunt
|
31
|
+
end
|
32
|
+
|
23
33
|
end
|
24
|
-
end
|
34
|
+
end
|
data/lib/scorpion/object.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "scorpion/attribute_set"
|
2
2
|
|
3
3
|
module Scorpion
|
4
4
|
# Identifies objects that are injected by {Scorpion scorpions} that inject
|
@@ -41,15 +41,8 @@ module Scorpion
|
|
41
41
|
# Create a new instance of this class with all non-lazy dependencies
|
42
42
|
# satisfied.
|
43
43
|
# @param [Hunt] hunt that this instance will be used to satisfy.
|
44
|
-
def self.spawn( hunt, *args,
|
45
|
-
object =
|
46
|
-
if dependencies.any?
|
47
|
-
new( *args, **dependencies, &block )
|
48
|
-
else
|
49
|
-
new( *args, &block )
|
50
|
-
end
|
51
|
-
|
52
|
-
|
44
|
+
def self.spawn( hunt, *args, &block )
|
45
|
+
object = new( *args, &block )
|
53
46
|
object.send :scorpion=, hunt.scorpion
|
54
47
|
|
55
48
|
# Go hunt for dependencies that are not lazy and initialize the
|
@@ -92,8 +85,8 @@ module Scorpion
|
|
92
85
|
injected_attributes.each do |attr|
|
93
86
|
next unless dependencies.key? attr.name
|
94
87
|
|
95
|
-
if overwrite || !
|
96
|
-
|
88
|
+
if overwrite || !send( "#{ attr.name }?" )
|
89
|
+
send( "#{ attr.name }=", dependencies[ attr.name ] )
|
97
90
|
end
|
98
91
|
end
|
99
92
|
|
@@ -107,8 +100,8 @@ module Scorpion
|
|
107
100
|
next unless dependencies.key? attr.name
|
108
101
|
val = dependencies.delete( attr.name )
|
109
102
|
|
110
|
-
if overwrite || !
|
111
|
-
|
103
|
+
if overwrite || !send( "#{ attr.name }?" )
|
104
|
+
send( "#{ attr.name }=", val )
|
112
105
|
end
|
113
106
|
end
|
114
107
|
|
@@ -117,18 +110,10 @@ module Scorpion
|
|
117
110
|
|
118
111
|
module ClassMethods
|
119
112
|
|
120
|
-
# Define an initializer that accepts injections.
|
121
|
-
# @param [Hash] arguments to accept in the initializer.
|
122
|
-
# @yield to initialize itself.
|
123
|
-
def initialize( arguments = {}, &block )
|
124
|
-
Scorpion::ObjectConstructor.new( self, arguments, &block ).define
|
125
|
-
end
|
126
|
-
|
127
113
|
# Tells a {Scorpion} what to inject into the class when it is constructed
|
128
114
|
# @return [nil]
|
129
115
|
# @see AttributeSet#define
|
130
|
-
def depend_on(
|
131
|
-
Scorpion::ObjectConstructor.new( self, arguments ).define if arguments.present?
|
116
|
+
def depend_on( &block )
|
132
117
|
injected_attributes.define &block
|
133
118
|
build_injected_attributes
|
134
119
|
validate_initializer_injections
|
@@ -137,11 +122,10 @@ module Scorpion
|
|
137
122
|
# Define a single dependency and accessor.
|
138
123
|
# @param [Symbol] name of the dependency.
|
139
124
|
# @param [Class,Module,Symbol] contract describing the desired behavior of the dependency.
|
140
|
-
|
141
|
-
|
142
|
-
attr = injected_attributes.define_attribute name, contract, *traits, &block
|
125
|
+
def attr_dependency( name, contract, &block )
|
126
|
+
attr = injected_attributes.define_attribute name, contract, &block
|
143
127
|
build_injected_attribute attr
|
144
|
-
|
128
|
+
adjust_injected_attribute_visibility attr
|
145
129
|
validate_initializer_injections
|
146
130
|
attr
|
147
131
|
end
|
@@ -169,6 +153,7 @@ module Scorpion
|
|
169
153
|
end
|
170
154
|
|
171
155
|
private
|
156
|
+
|
172
157
|
def validate_initializer_injections
|
173
158
|
initializer_injections.each do |attr|
|
174
159
|
injected = injected_attributes[ attr.name ]
|
@@ -181,7 +166,7 @@ module Scorpion
|
|
181
166
|
def build_injected_attributes
|
182
167
|
injected_attributes.each do |attr|
|
183
168
|
build_injected_attribute attr
|
184
|
-
|
169
|
+
adjust_injected_attribute_visibility attr
|
185
170
|
end
|
186
171
|
end
|
187
172
|
|
@@ -190,7 +175,7 @@ module Scorpion
|
|
190
175
|
def #{ attr.name }
|
191
176
|
@#{ attr.name } ||= begin
|
192
177
|
attr = injected_attributes[ :#{ attr.name } ]
|
193
|
-
scorpion.
|
178
|
+
( scorpion_hunt || scorpion ).fetch( attr.contract )
|
194
179
|
end
|
195
180
|
end
|
196
181
|
|
@@ -204,7 +189,7 @@ module Scorpion
|
|
204
189
|
RUBY
|
205
190
|
end
|
206
191
|
|
207
|
-
def
|
192
|
+
def adjust_injected_attribute_visibility( attr )
|
208
193
|
unless attr.public?
|
209
194
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
210
195
|
private :#{ attr.name }=
|
@@ -220,4 +205,4 @@ module Scorpion
|
|
220
205
|
end
|
221
206
|
end
|
222
207
|
end
|
223
|
-
end
|
208
|
+
end
|
data/lib/scorpion/rack.rb
CHANGED
@@ -4,7 +4,7 @@ module Scorpion
|
|
4
4
|
module Rack
|
5
5
|
class Middleware
|
6
6
|
|
7
|
-
ENV_KEY =
|
7
|
+
ENV_KEY = "scorpion.rack.instance".freeze
|
8
8
|
|
9
9
|
def initialize( app, nest = nil )
|
10
10
|
@app = app
|
@@ -19,6 +19,7 @@ module Scorpion
|
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
22
|
+
|
22
23
|
attr_reader :nest
|
23
24
|
|
24
25
|
def prepare_scorpion( scorpion, env )
|
data/lib/scorpion/rails.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Scorpion
|
2
2
|
module Rails
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
3
|
+
require "scorpion/rails/nest"
|
4
|
+
require "scorpion/rails/job"
|
5
|
+
require "scorpion/rails/mailer"
|
6
|
+
require "scorpion/rails/active_record"
|
7
|
+
require "scorpion/rails/controller"
|
8
|
+
require "scorpion/rails/railtie"
|
9
9
|
end
|
10
10
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Scorpion
|
2
2
|
module Rails
|
3
3
|
module ActiveRecord
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
4
|
+
require "scorpion/rails/active_record/model"
|
5
|
+
require "scorpion/rails/active_record/relation"
|
6
|
+
require "scorpion/rails/active_record/association"
|
7
7
|
|
8
8
|
# Setup scorpion support for activerecord
|
9
9
|
def self.install!
|
@@ -13,7 +13,7 @@ module Scorpion
|
|
13
13
|
::ActiveRecord::Relation.send :prepend, Scorpion::Rails::ActiveRecord::Relation
|
14
14
|
::ActiveRecord::Associations::Association.send :prepend, Scorpion::Rails::ActiveRecord::Association
|
15
15
|
|
16
|
-
# TODO extend Scorpion::Hunter to support AR
|
16
|
+
# TODO: extend Scorpion::Hunter to support AR
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -46,11 +46,11 @@ module Scorpion
|
|
46
46
|
next unless klass.instance_methods.include? method
|
47
47
|
|
48
48
|
mod = Module.new do
|
49
|
-
module_eval <<-
|
49
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
50
50
|
def #{ method }( *args, &block )
|
51
51
|
sting! super
|
52
52
|
end
|
53
|
-
|
53
|
+
RUBY
|
54
54
|
end
|
55
55
|
|
56
56
|
klass.prepend mod
|
@@ -61,4 +61,4 @@ module Scorpion
|
|
61
61
|
|
62
62
|
end
|
63
63
|
end
|
64
|
-
end
|
64
|
+
end
|