scorpion-ioc 0.4.0 → 0.5.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/.rspec +0 -1
- data/Gemfile +0 -1
- data/README.md +4 -1
- data/lib/scorpion.rb +38 -11
- data/lib/scorpion/attribute.rb +4 -1
- data/lib/scorpion/chain_hunter.rb +58 -0
- data/lib/scorpion/dependency.rb +7 -3
- data/lib/scorpion/dependency/builder_dependency.rb +5 -1
- data/lib/scorpion/dependency/class_dependency.rb +10 -7
- data/lib/scorpion/dependency_map.rb +11 -2
- data/lib/scorpion/error.rb +6 -0
- data/lib/scorpion/hunt.rb +32 -21
- data/lib/scorpion/hunter.rb +15 -2
- data/lib/scorpion/locale/en.yml +1 -0
- data/lib/scorpion/method.rb +24 -0
- data/lib/scorpion/nest.rb +5 -0
- data/lib/scorpion/object.rb +30 -23
- data/lib/scorpion/object_constructor.rb +23 -14
- data/lib/scorpion/rails.rb +1 -0
- data/lib/scorpion/rails/active_record/association.rb +5 -6
- data/lib/scorpion/rails/active_record/model.rb +4 -5
- data/lib/scorpion/rails/active_record/relation.rb +2 -4
- data/lib/scorpion/rails/controller.rb +31 -2
- data/lib/scorpion/rails/job.rb +12 -0
- data/lib/scorpion/rails/mailer.rb +42 -0
- data/lib/scorpion/rails/nest.rb +23 -20
- data/lib/scorpion/rails/railtie.rb +1 -0
- data/lib/scorpion/rspec/helper.rb +47 -0
- data/lib/scorpion/stinger.rb +0 -1
- data/lib/scorpion/version.rb +1 -1
- data/scorpion.gemspec +1 -0
- data/spec/lib/scorpion/attribute_spec.rb +10 -0
- data/spec/lib/scorpion/hunt_spec.rb +9 -3
- data/spec/lib/scorpion/hunter_spec.rb +13 -2
- data/spec/lib/scorpion/object_constructor_spec.rb +63 -6
- data/spec/lib/scorpion/object_spec.rb +9 -5
- data/spec/lib/scorpion/rails/controller_spec.rb +33 -1
- data/spec/lib/scorpion/rspec/helper_spec.rb +10 -0
- data/spec/spec_helper.rb +5 -0
- metadata +20 -3
data/lib/scorpion/hunter.rb
CHANGED
@@ -32,6 +32,15 @@ module Scorpion
|
|
32
32
|
dependency_map.chart &block
|
33
33
|
end
|
34
34
|
|
35
|
+
# Expose dependency injection definitions as top-level methods.
|
36
|
+
[:hunt_for,:capture,:share].each do |delegate|
|
37
|
+
define_method delegate do |*args,&block|
|
38
|
+
prepare do |hunter|
|
39
|
+
hunter.send delegate, *args, &block
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
35
44
|
# @see Scorpion#replicate
|
36
45
|
def replicate
|
37
46
|
replica = self.class.new self
|
@@ -40,16 +49,20 @@ module Scorpion
|
|
40
49
|
end
|
41
50
|
|
42
51
|
# @see Scorpion#hunt
|
43
|
-
def execute( hunt )
|
52
|
+
def execute( hunt, explicit_only = false )
|
44
53
|
dependency = dependency_map.find( hunt.contract, hunt.traits )
|
45
54
|
dependency ||= parent.dependency_map.find( hunt.contract, hunt.traits ) if parent
|
46
|
-
dependency ||= Dependency.define( hunt.contract ) if hunt.traits.blank?
|
55
|
+
dependency ||= Dependency.define( hunt.contract ) if hunt.traits.blank? && !explicit_only
|
47
56
|
|
48
57
|
unsuccessful_hunt( hunt.contract, hunt.traits ) unless dependency
|
49
58
|
|
50
59
|
dependency.fetch hunt
|
51
60
|
end
|
52
61
|
|
62
|
+
# @see Scorpion#reset
|
63
|
+
def reset
|
64
|
+
dependency_map.reset
|
65
|
+
end
|
53
66
|
|
54
67
|
end
|
55
68
|
end
|
data/lib/scorpion/locale/en.yml
CHANGED
@@ -4,6 +4,7 @@ en:
|
|
4
4
|
messages:
|
5
5
|
unsuccessful_hunt: "Couldn't find a %{contract} builder with traits '%{traits}'"
|
6
6
|
builder_required: A custom builder must be provided to resolve this dependency
|
7
|
+
arity_mismatch: The block must accept %{expected} arguments, but actually expects %{actual}
|
7
8
|
warnings:
|
8
9
|
messages:
|
9
10
|
mixed_scorpions: A scorpion has already been assigned. Mixing scorpions can result in unexpected results.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Scorpion
|
2
|
+
# Adds a #scorpion method to an object.
|
3
|
+
module Method
|
4
|
+
# @overload scorpion
|
5
|
+
# @return [Scorpion] the object's scorpion used to hunt down dependencies.
|
6
|
+
# @overload scorpion( scope )
|
7
|
+
# Stings the given `scope` with the current scorpion.
|
8
|
+
# @param [#with_scorpion] scope an object that responds to #with_scorpion that
|
9
|
+
# receives the current scorpion.
|
10
|
+
# @return [scope] stung object.
|
11
|
+
def scorpion( scope = nil )
|
12
|
+
if scope
|
13
|
+
scope.with_scorpion( scorpion )
|
14
|
+
else
|
15
|
+
@scorpion
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private def scorpion=( value )
|
20
|
+
@scorpion = value
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/lib/scorpion/nest.rb
CHANGED
data/lib/scorpion/object.rb
CHANGED
@@ -9,10 +9,7 @@ module Scorpion
|
|
9
9
|
# @!group Attributes
|
10
10
|
#
|
11
11
|
|
12
|
-
|
13
|
-
# @return [Scorpion] the scorpion used to hunt down dependencies.
|
14
|
-
attr_accessor :scorpion
|
15
|
-
private :scorpion=
|
12
|
+
include Scorpion::Method
|
16
13
|
|
17
14
|
# @!attribute
|
18
15
|
# @return [Scorpion::AttributeSet] the set of injected attributes and their
|
@@ -35,8 +32,8 @@ module Scorpion
|
|
35
32
|
send "#{ attribute.name }=", dependency
|
36
33
|
end
|
37
34
|
|
38
|
-
#
|
39
|
-
def self.
|
35
|
+
# Infest the object with a scoprion and prepare it to be fed.
|
36
|
+
def self.infest( base )
|
40
37
|
base.extend Scorpion::Object::ClassMethods
|
41
38
|
if base.is_a? Class
|
42
39
|
base.class_exec do
|
@@ -44,32 +41,38 @@ module Scorpion
|
|
44
41
|
# Create a new instance of this class with all non-lazy dependencies
|
45
42
|
# satisfied.
|
46
43
|
# @param [Hunt] hunt that this instance will be used to satisfy.
|
47
|
-
def self.spawn( hunt, *args, &block )
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
44
|
+
def self.spawn( hunt, *args, **dependencies, &block )
|
45
|
+
object =
|
46
|
+
if dependencies.any?
|
47
|
+
new( *args, **dependencies, &block )
|
48
|
+
else
|
49
|
+
new( *args, &block )
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
object.send :scorpion=, hunt.scorpion
|
54
|
+
|
55
|
+
# Go hunt for dependencies that are not lazy and initialize the
|
56
|
+
# references.
|
57
|
+
hunt.inject object
|
58
|
+
object
|
56
59
|
end
|
57
60
|
|
58
61
|
end
|
59
62
|
|
60
63
|
base.subclasses.each do |sub|
|
61
|
-
|
64
|
+
infest( sub ) unless sub < Scorpion::Object
|
62
65
|
end
|
63
66
|
end
|
64
67
|
end
|
65
68
|
|
66
69
|
def self.included( base )
|
67
|
-
|
70
|
+
infest( base )
|
68
71
|
super
|
69
72
|
end
|
70
73
|
|
71
74
|
def self.prepended( base )
|
72
|
-
|
75
|
+
infest( base )
|
73
76
|
super
|
74
77
|
end
|
75
78
|
|
@@ -117,14 +120,15 @@ module Scorpion
|
|
117
120
|
# Define an initializer that accepts injections.
|
118
121
|
# @param [Hash] arguments to accept in the initializer.
|
119
122
|
# @yield to initialize itself.
|
120
|
-
def initialize( arguments, &block )
|
123
|
+
def initialize( arguments = {}, &block )
|
121
124
|
Scorpion::ObjectConstructor.new( self, arguments, &block ).define
|
122
125
|
end
|
123
126
|
|
124
127
|
# Tells a {Scorpion} what to inject into the class when it is constructed
|
125
128
|
# @return [nil]
|
126
129
|
# @see AttributeSet#define
|
127
|
-
def depend_on( &block )
|
130
|
+
def depend_on( arguments = nil, &block )
|
131
|
+
Scorpion::ObjectConstructor.new( self, arguments ).define if arguments.present?
|
128
132
|
injected_attributes.define &block
|
129
133
|
build_injected_attributes
|
130
134
|
end
|
@@ -155,8 +159,11 @@ module Scorpion
|
|
155
159
|
# @return [Scorpion::AttributeSet] the set of injected attriutes.
|
156
160
|
def initializer_injections
|
157
161
|
@initializer_injections ||= begin
|
158
|
-
|
159
|
-
|
162
|
+
if superclass.respond_to?( :initializer_injections )
|
163
|
+
superclass.initializer_injections
|
164
|
+
else
|
165
|
+
AttributeSet.new
|
166
|
+
end
|
160
167
|
end
|
161
168
|
end
|
162
169
|
|
@@ -174,7 +181,7 @@ module Scorpion
|
|
174
181
|
def #{ attr.name }
|
175
182
|
@#{ attr.name } ||= begin
|
176
183
|
attr = injected_attributes[ :#{ attr.name } ]
|
177
|
-
scorpion.
|
184
|
+
scorpion.fetch_by_traits( attr.contract, attr.traits )
|
178
185
|
end
|
179
186
|
end
|
180
187
|
|
@@ -9,10 +9,11 @@ module Scorpion
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def define
|
12
|
-
@signature
|
13
|
-
@
|
12
|
+
@signature = []
|
13
|
+
@block_signature = []
|
14
|
+
@body = []
|
14
15
|
|
15
|
-
|
16
|
+
define_dependencies
|
16
17
|
build_body
|
17
18
|
|
18
19
|
add_initialize_block
|
@@ -20,35 +21,43 @@ module Scorpion
|
|
20
21
|
end
|
21
22
|
|
22
23
|
private
|
23
|
-
attr_reader :base, :arguments, :block, :body
|
24
|
+
attr_reader :base, :arguments, :block, :body
|
24
25
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
26
|
+
def define_dependencies
|
27
|
+
# Override the inherited injections cause we're about to define a new
|
28
|
+
# initializer.
|
29
|
+
base.instance_variable_set :@initializer_injections, AttributeSet.new
|
28
30
|
|
31
|
+
arguments.each do |key,expectation|
|
29
32
|
base.initializer_injections.define_attribute key, *Array( expectation )
|
30
33
|
base.attr_dependency key, *Array( expectation )
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
34
37
|
def build_body
|
35
|
-
arguments.
|
36
|
-
body << "
|
38
|
+
if arguments.present?
|
39
|
+
body << "injections = dependencies.slice( :#{ arguments.keys.join(', :') } )"
|
40
|
+
body << "inject_from( dependencies )"
|
37
41
|
end
|
42
|
+
body << "super" if base.superclass < Scorpion::Object
|
38
43
|
end
|
39
44
|
|
40
45
|
def add_initialize_block
|
41
46
|
if block
|
42
|
-
|
43
|
-
|
47
|
+
name = "__initialize_with_block_#{ base.name || base.object_id }"
|
48
|
+
body << "#{ name }( *args, **injections, &block )"
|
49
|
+
base.send :define_method, :"#{ name }", &block
|
44
50
|
end
|
45
51
|
end
|
46
52
|
|
47
53
|
def assemble
|
54
|
+
source = %Q|def initialize( *args, **dependencies, &block )\n\t#{ body.join( "\n\t" ) }\nend|
|
55
|
+
|
56
|
+
# puts base.name
|
57
|
+
# puts source
|
58
|
+
|
48
59
|
base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
49
|
-
|
50
|
-
#{ body }
|
51
|
-
end
|
60
|
+
#{ source }
|
52
61
|
RUBY
|
53
62
|
end
|
54
63
|
end
|
data/lib/scorpion/rails.rb
CHANGED
@@ -10,12 +10,11 @@ module Scorpion
|
|
10
10
|
# @!group Attributes
|
11
11
|
#
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
13
|
+
include Scorpion::Method
|
14
|
+
|
15
|
+
def scorpion( scope = nil )
|
16
|
+
super || owner.scorpion( scope )
|
17
|
+
end
|
19
18
|
|
20
19
|
#
|
21
20
|
# @!endgroup Attributes
|
@@ -9,12 +9,11 @@ module Scorpion
|
|
9
9
|
def self.prepended( base )
|
10
10
|
# Setup dependency injection
|
11
11
|
base.send :include, Scorpion::Object
|
12
|
-
base.
|
13
|
-
|
14
|
-
|
12
|
+
base.singleton_class.class_exec do
|
13
|
+
delegate :with_scorpion, to: :all
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
delegate :with_scorpion, to: :all
|
16
|
+
super
|
18
17
|
end
|
19
18
|
|
20
19
|
def association( *args, &block )
|
@@ -11,9 +11,7 @@ module Scorpion
|
|
11
11
|
# @!group Attributes
|
12
12
|
#
|
13
13
|
|
14
|
-
|
15
|
-
# @return [Scorpion] the scorpion serving the relation.
|
16
|
-
attr_accessor :scorpion
|
14
|
+
include Scorpion::Method
|
17
15
|
|
18
16
|
#
|
19
17
|
# @!endgroup Attributes
|
@@ -27,7 +25,7 @@ module Scorpion
|
|
27
25
|
# User.with_scorpion( scorpion ).where( ... )
|
28
26
|
def with_scorpion( scorpion )
|
29
27
|
spawn.tap do |other|
|
30
|
-
other.scorpion
|
28
|
+
other.send :scorpion=, scorpion
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
@@ -8,14 +8,41 @@ module Scorpion
|
|
8
8
|
|
9
9
|
ENV_KEY = 'scorpion.instance'.freeze
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
# Fetch an object from the controller's {#scorpion}.
|
13
|
+
# @see Scorpion#fetch
|
14
|
+
def fetch( *args, &block )
|
15
|
+
scorpion.fetch *args, &block
|
13
16
|
end
|
17
|
+
private :fetch
|
18
|
+
|
19
|
+
|
20
|
+
# @overload scorpion
|
21
|
+
# @return [Scorpion] the current scorpion
|
22
|
+
# @overload scorpion( scope )
|
23
|
+
# Stings the given `scope` with the current scorpion.
|
24
|
+
# @param [ActiveRecord::Relation,#with_scorpion] an ActiveRecord relation,
|
25
|
+
# scope or model class.
|
26
|
+
# @return [ActiveRecord::Relation] scorpion scoped relation.
|
14
27
|
|
15
28
|
def self.included( base )
|
16
29
|
# Setup dependency injection
|
30
|
+
base.send :include, Scorpion::Object
|
17
31
|
base.send :include, Scorpion::Rails::Nest
|
32
|
+
|
18
33
|
base.around_filter :with_scorpion
|
34
|
+
|
35
|
+
base.class_eval do
|
36
|
+
# Defined here to override the #scorpion method provided by Scorpion::Object.
|
37
|
+
def scorpion( scope = nil )
|
38
|
+
if scope
|
39
|
+
super
|
40
|
+
else
|
41
|
+
ensure_scorpion( env[ENV_KEY] )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
19
46
|
super
|
20
47
|
end
|
21
48
|
|
@@ -42,6 +69,8 @@ module Scorpion
|
|
42
69
|
end
|
43
70
|
|
44
71
|
def free_scorpion
|
72
|
+
scorpion.try( :destroy )
|
73
|
+
env.delete ENV_KEY
|
45
74
|
end
|
46
75
|
|
47
76
|
end
|
data/lib/scorpion/rails/job.rb
CHANGED
@@ -6,8 +6,10 @@ module Scorpion
|
|
6
6
|
# Adds a scorpion nest to support injection into rails background worker jobs.
|
7
7
|
module Job
|
8
8
|
|
9
|
+
|
9
10
|
def self.included( base )
|
10
11
|
# Setup dependency injection
|
12
|
+
base.send :include, Scorpion::Object
|
11
13
|
base.send :include, Scorpion::Rails::Nest
|
12
14
|
base.send :around_perform do |job, block|
|
13
15
|
job.with_scorpion &block
|
@@ -25,6 +27,16 @@ module Scorpion
|
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
30
|
+
|
31
|
+
attr_reader :scorpion
|
32
|
+
def assign_scorpion( scorpion )
|
33
|
+
@scorpion = scorpion
|
34
|
+
end
|
35
|
+
|
36
|
+
def free_scorpion
|
37
|
+
@scorpion.try( :destroy )
|
38
|
+
@scorpion = nil
|
39
|
+
end
|
28
40
|
end
|
29
41
|
end
|
30
42
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'scorpion/nest'
|
2
|
+
|
3
|
+
module Scorpion
|
4
|
+
module Rails
|
5
|
+
|
6
|
+
# Adds a scorpion nest to support injection into rails mailers.
|
7
|
+
module Mailer
|
8
|
+
|
9
|
+
|
10
|
+
def self.included( base )
|
11
|
+
# Setup dependency injection
|
12
|
+
base.send :include, Scorpion::Object
|
13
|
+
base.send :include, Scorpion::Rails::Nest
|
14
|
+
base.send :around_filter do |mailer, block|
|
15
|
+
mailer.with_scorpion &block
|
16
|
+
end
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def prepare_scorpion( scorpion )
|
24
|
+
scorpion.prepare do |hunter|
|
25
|
+
hunter.hunt_for ActionMailer::Base do
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :scorpion
|
32
|
+
def assign_scorpion( scorpion )
|
33
|
+
@scorpion = scorpion
|
34
|
+
end
|
35
|
+
|
36
|
+
def free_scorpion
|
37
|
+
@scorpion.try( :destroy )
|
38
|
+
@scorpion = nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|