scorpion-ioc 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rspec +2 -1
  4. data/README.md +111 -44
  5. data/lib/scorpion/attribute.rb +0 -1
  6. data/lib/scorpion/attribute_set.rb +15 -7
  7. data/lib/scorpion/dependency/argument_dependency.rb +25 -0
  8. data/lib/scorpion/{prey/builder_prey.rb → dependency/builder_dependency.rb} +8 -8
  9. data/lib/scorpion/dependency/captured_dependency.rb +44 -0
  10. data/lib/scorpion/dependency/class_dependency.rb +25 -0
  11. data/lib/scorpion/dependency/module_dependency.rb +14 -0
  12. data/lib/scorpion/dependency.rb +137 -0
  13. data/lib/scorpion/dependency_map.rb +135 -0
  14. data/lib/scorpion/hunt.rb +158 -0
  15. data/lib/scorpion/hunter.rb +21 -20
  16. data/lib/scorpion/locale/en.yml +5 -1
  17. data/lib/scorpion/{king.rb → object.rb} +72 -53
  18. data/lib/scorpion/object_constructor.rb +55 -0
  19. data/lib/scorpion/rails/active_record/association.rb +65 -0
  20. data/lib/scorpion/rails/active_record/model.rb +28 -0
  21. data/lib/scorpion/rails/active_record/relation.rb +66 -0
  22. data/lib/scorpion/rails/active_record.rb +21 -0
  23. data/lib/scorpion/rails/controller.rb +22 -62
  24. data/lib/scorpion/rails/job.rb +30 -0
  25. data/lib/scorpion/rails/nest.rb +86 -0
  26. data/lib/scorpion/rails/railtie.rb +16 -0
  27. data/lib/scorpion/rails.rb +4 -0
  28. data/lib/scorpion/rspec/helper.rb +25 -0
  29. data/lib/scorpion/rspec.rb +17 -0
  30. data/lib/scorpion/stinger.rb +69 -0
  31. data/lib/scorpion/version.rb +1 -1
  32. data/lib/scorpion.rb +91 -44
  33. data/scorpion.gemspec +1 -1
  34. data/spec/internal/app/models/author.rb +17 -0
  35. data/spec/internal/app/models/todo.rb +14 -0
  36. data/spec/internal/db/schema.rb +12 -1
  37. data/spec/lib/scorpion/dependency/argument_dependency_spec.rb +18 -0
  38. data/spec/lib/scorpion/dependency/builder_dependency_spec.rb +41 -0
  39. data/spec/lib/scorpion/dependency/module_dependency_spec.rb +16 -0
  40. data/spec/lib/scorpion/dependency_map_spec.rb +108 -0
  41. data/spec/lib/scorpion/dependency_spec.rb +131 -0
  42. data/spec/lib/scorpion/hunt_spec.rb +93 -0
  43. data/spec/lib/scorpion/hunter_spec.rb +53 -14
  44. data/spec/lib/scorpion/object_constructor_spec.rb +49 -0
  45. data/spec/lib/scorpion/object_spec.rb +214 -0
  46. data/spec/lib/scorpion/rails/active_record/association_spec.rb +26 -0
  47. data/spec/lib/scorpion/rails/active_record/model_spec.rb +33 -0
  48. data/spec/lib/scorpion/rails/active_record/relation_spec.rb +72 -0
  49. data/spec/lib/scorpion/rails/controller_spec.rb +9 -9
  50. data/spec/lib/scorpion/rails/job_spec.rb +34 -0
  51. data/spec/lib/scorpion/rspec/helper_spec.rb +44 -0
  52. data/spec/lib/scorpion_spec.rb +0 -35
  53. data/spec/spec_helper.rb +1 -0
  54. metadata +54 -26
  55. data/lib/scorpion/hunting_map.rb +0 -139
  56. data/lib/scorpion/prey/captured_prey.rb +0 -44
  57. data/lib/scorpion/prey/class_prey.rb +0 -13
  58. data/lib/scorpion/prey/hunted_prey.rb +0 -14
  59. data/lib/scorpion/prey/module_prey.rb +0 -14
  60. data/lib/scorpion/prey.rb +0 -94
  61. data/spec/internal/db/combustion_test.sqlite +0 -0
  62. data/spec/lib/scorpion/hunting_map_spec.rb +0 -126
  63. data/spec/lib/scorpion/instance_spec.rb +0 -5
  64. data/spec/lib/scorpion/king_spec.rb +0 -198
  65. data/spec/lib/scorpion/prey/builder_prey_spec.rb +0 -42
  66. data/spec/lib/scorpion/prey/module_prey_spec.rb +0 -16
  67. data/spec/lib/scorpion/prey_spec.rb +0 -76
@@ -1,17 +1,18 @@
1
1
  require 'scorpion/attribute_set'
2
2
 
3
3
  module Scorpion
4
- # Identifies objects that are served by {Scorpion scorpions} that feed on
5
- # {Scorpion#hunt hunted} prey.
6
- module King
4
+ # Identifies objects that are injected by {Scorpion scorpions} that inject
5
+ # {Scorpion#hunt hunted} dependencies.
6
+ module Object
7
7
 
8
8
  # ============================================================================
9
9
  # @!group Attributes
10
10
  #
11
11
 
12
12
  # @!attribute
13
- # @return [Scorpion] the scorpion used to hunt down prey.
14
- attr_reader :scorpion
13
+ # @return [Scorpion] the scorpion used to hunt down dependencies.
14
+ attr_accessor :scorpion
15
+ private :scorpion=
15
16
 
16
17
  # @!attribute
17
18
  # @return [Scorpion::AttributeSet] the set of injected attributes and their
@@ -23,74 +24,68 @@ module Scorpion
23
24
  #
24
25
  # @!endgroup Attributes
25
26
 
26
- # Feeds one of the {#injected_attributes} to the object.
27
+ # Injects one of the {#injected_attributes} into the object.
27
28
  # @param [Scorpion::Attribute] attribute to be fed.
28
- # @param [Object] food the value of the attribute
29
+ # @param [Object] dependency the value of the attribute
29
30
  # @visibility private
30
31
  #
31
- # This method is used by the {#scorpion} to feed the king. Do not call it
32
+ # This method is used by the {#scorpion} to feed the object. Do not call it
32
33
  # directly.
33
- def feed( attribute, food )
34
- send "#{ attribute.name }=", food
34
+ def inject( attribute, dependency )
35
+ send "#{ attribute.name }=", dependency
35
36
  end
36
37
 
37
- # Crown the object as a king and prepare it to be fed.
38
+ # Crown the object as a object and prepare it to be fed.
38
39
  def self.crown( base )
39
- base.extend Scorpion::King::ClassMethods
40
+ base.extend Scorpion::Object::ClassMethods
40
41
  if base.is_a? Class
41
42
  base.class_exec do
42
43
 
43
- # Span a new instance of this class with all non-lazy dependencies
44
+ # Create a new instance of this class with all non-lazy dependencies
44
45
  # satisfied.
45
- # @param [Scorpion] scorpion that will hunt for dependencies.
46
- def self.spawn( scorpion, *args, &block )
47
- new( *args, &block ).tap do |king|
48
- king.instance_variable_set :@scorpion, scorpion
46
+ # @param [Hunt] hunt that this instance will be used to satisfy.
47
+ def self.spawn( hunt, *args, &block )
48
+ new( *args, &block ).tap do |object|
49
+ object.send :scorpion=, hunt.scorpion
50
+
49
51
  # Go hunt for dependencies that are not lazy and initialize the
50
52
  # references.
51
- scorpion.feed king
52
- king.send :on_fed
53
+ hunt.inject object
54
+ object.send :on_injected
53
55
  end
54
56
  end
57
+
58
+ end
59
+
60
+ base.subclasses.each do |sub|
61
+ crown( sub ) unless sub < Scorpion::Object
55
62
  end
56
63
  end
57
64
  end
58
65
 
59
- def self.included( base )
60
- crown( base )
61
- super
62
- end
66
+ def self.included( base )
67
+ crown( base )
68
+ super
69
+ end
63
70
 
64
- def self.prepended( base )
65
- crown( base )
66
- super
67
- end
71
+ def self.prepended( base )
72
+ crown( base )
73
+ super
74
+ end
68
75
 
69
76
 
70
77
  private
71
78
 
72
- # Called after the king has been initialized and feed all its required
79
+ # Called after the object has been initialized and feed all its required
73
80
  # dependencies. It should be used in place of #initialize when the
74
81
  # constructor needs access to injected attributes.
75
- def on_fed
76
- end
77
-
78
- # Convenience method to ask the {#scorpion} to hunt for an object.
79
- # @see Scorpion#hunt
80
- def hunt( contract, *args, &block )
81
- scorpion.hunt contract, *args, &block
82
- end
83
-
84
- # Convenience method to ask the {#scorpion} to hunt for an object.
85
- # @see Scorpion#hunt_by_traits
86
- def hunt_by_traits( contract, traits, *args, &block )
87
- scorpion.hunt_by_traits contract, *args, &block
82
+ def on_injected
88
83
  end
89
84
 
90
85
  # Feed dependencies from a hash into their associated attributes.
91
86
  # @param [Hash] dependencies hash describing attributes to inject.
92
87
  # @param [Boolean] overwrite existing attributes with values in in the hash.
93
- def feast_on( dependencies, overwrite = false )
88
+ def inject_from( dependencies, overwrite = false )
94
89
  injected_attributes.each do |attr|
95
90
  next unless dependencies.key? attr.name
96
91
 
@@ -101,11 +96,10 @@ module Scorpion
101
96
 
102
97
  dependencies
103
98
  end
104
- alias_method :inject_from, :feast_on
105
99
 
106
100
  # Injects dependenices from the hash and removes them from the hash.
107
- # @see #feast_on
108
- def feast_on!( dependencies, overwrite = false )
101
+ # @see #inject_from
102
+ def inject_from!( dependencies, overwrite = false )
109
103
  injected_attributes.each do |attr|
110
104
  next unless dependencies.key? attr.name
111
105
  val = dependencies.delete( attr.name )
@@ -117,27 +111,52 @@ module Scorpion
117
111
 
118
112
  dependencies
119
113
  end
120
- alias_method :inject_from!, :feast_on!
121
114
 
122
115
  module ClassMethods
123
116
 
117
+ # Define an initializer that accepts injections.
118
+ # @param [Hash] arguments to accept in the initializer.
119
+ # @yield to initialize itself.
120
+ def initialize( arguments, &block )
121
+ Scorpion::ObjectConstructor.new( self, arguments, &block ).define
122
+ end
123
+
124
124
  # Tells a {Scorpion} what to inject into the class when it is constructed
125
125
  # @return [nil]
126
126
  # @see AttributeSet#define
127
- def feed_on( &block )
127
+ def depend_on( &block )
128
128
  injected_attributes.define &block
129
129
  build_injected_attributes
130
130
  end
131
- alias_method :inject, :feed_on
132
- alias_method :depend_on, :feed_on
131
+ alias_method :inject, :depend_on
132
+ alias_method :depend_on, :depend_on
133
+
134
+ # Define a single dependency and accessor.
135
+ # @param [Symbol] name of the dependency.
136
+ # @param [Class,Module,Symbol] contract describing the desired behavior of the dependency.
137
+ # @param [Array<Symbol>] traits found on the {Dependency}.
138
+ def attr_dependency( name, contract, *traits, &block )
139
+ attr = injected_attributes.define_attribute name, contract, *traits, &block
140
+ build_injected_attribute attr
141
+ set_injected_attribute_visibility attr
142
+ end
133
143
 
134
144
  # @!attribute
135
145
  # @return [Scorpion::AttributeSet] the set of injected attriutes.
136
146
  def injected_attributes
137
147
  @injected_attributes ||= begin
138
- attr = AttributeSet.new
139
- attr.inherit! superclass.injected_attributes if superclass.respond_to? :injected_attributes
140
- attr
148
+ attrs = AttributeSet.new
149
+ attrs.inherit! superclass.injected_attributes if superclass.respond_to? :injected_attributes
150
+ attrs
151
+ end
152
+ end
153
+
154
+ # @!attribute
155
+ # @return [Scorpion::AttributeSet] the set of injected attriutes.
156
+ def initializer_injections
157
+ @initializer_injections ||= begin
158
+ attrs = AttributeSet.new
159
+ attrs
141
160
  end
142
161
  end
143
162
 
@@ -155,7 +174,7 @@ module Scorpion
155
174
  def #{ attr.name }
156
175
  @#{ attr.name } ||= begin
157
176
  attr = injected_attributes[ :#{ attr.name } ]
158
- scorpion.hunt( attr.contract, attr.traits )
177
+ scorpion.fetch( attr.contract, attr.traits )
159
178
  end
160
179
  end
161
180
 
@@ -0,0 +1,55 @@
1
+ module Scorpion
2
+ # Builds an injectable constructor for a Scorpion::Object.
3
+ class ObjectConstructor
4
+
5
+ def initialize( base, arguments, &block )
6
+ @base = base
7
+ @arguments = arguments
8
+ @block = block
9
+ end
10
+
11
+ def define
12
+ @signature = []
13
+ @body = ""
14
+
15
+ build_signature
16
+ build_body
17
+
18
+ add_initialize_block
19
+ assemble
20
+ end
21
+
22
+ private
23
+ attr_reader :base, :arguments, :block, :body, :signature
24
+
25
+ def build_signature
26
+ arguments.each do |key,expectation|
27
+ signature << key
28
+
29
+ base.initializer_injections.define_attribute key, *Array( expectation )
30
+ base.attr_dependency key, *Array( expectation )
31
+ end
32
+ end
33
+
34
+ def build_body
35
+ arguments.each do |key,expectation|
36
+ body << "@#{ key } = #{ key };"
37
+ end
38
+ end
39
+
40
+ def add_initialize_block
41
+ if block
42
+ body << "__initialize_with_block( &block )"
43
+ base.send :define_method, :__initialize_with_block, &block
44
+ end
45
+ end
46
+
47
+ def assemble
48
+ base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
49
+ def initialize( #{ signature.join( ', ' ) }, &block )
50
+ #{ body }
51
+ end
52
+ RUBY
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,65 @@
1
+ module Scorpion
2
+ module Rails
3
+ module ActiveRecord
4
+
5
+ # Adds dependency injection to ActiveRecord::Base model associations.
6
+ module Association
7
+ include Scorpion::Stinger
8
+
9
+ # ============================================================================
10
+ # @!group Attributes
11
+ #
12
+
13
+ # @!attribute
14
+ # @return [Scorpion] the scorpion serving the association.
15
+ attr_accessor :scorpion
16
+ def scorpion
17
+ @scorpion || owner.scorpion
18
+ end
19
+
20
+ #
21
+ # @!endgroup Attributes
22
+
23
+
24
+ # Make sure we override the methods of child classes as well.
25
+ def self.prepended( base )
26
+ infect base
27
+ super
28
+ end
29
+
30
+ # Propagate the module inheritance to all derived classes so that we can
31
+ # always overlay our interception methods on the top-most overriden
32
+ # method.
33
+ def self.infect( klass )
34
+ klass.class_exec do
35
+ def self.inherited( from )
36
+ Scorpion::Rails::ActiveRecord::Association.infect( from )
37
+
38
+ super
39
+ end
40
+ end
41
+ overlay( klass )
42
+ end
43
+
44
+ # Overlay interception methods on the klass.
45
+ def self.overlay( klass )
46
+ [ :load_target, :target, :reader, :writer, :scope ].each do |method|
47
+ next unless klass.instance_methods.include? method
48
+
49
+ mod = Module.new do
50
+ module_eval <<-EOS, __FILE__, __LINE__ + 1
51
+ def #{ method }( *args, &block )
52
+ sting! super
53
+ end
54
+ EOS
55
+ end
56
+
57
+ klass.prepend mod
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,28 @@
1
+ module Scorpion
2
+ module Rails
3
+ module ActiveRecord
4
+
5
+ # Adds dependency injection to ActiveRecord::Base models.
6
+ module Model
7
+ include Scorpion::Stinger
8
+
9
+ def self.prepended( base )
10
+ # Setup dependency injection
11
+ base.send :include, Scorpion::Object
12
+ base.send :extend, ClassMethods
13
+ super
14
+ end
15
+
16
+ module ClassMethods
17
+ delegate :with_scorpion, to: :all
18
+ end
19
+
20
+ def association( *args, &block )
21
+ sting! super
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,66 @@
1
+ module Scorpion
2
+ module Rails
3
+ module ActiveRecord
4
+
5
+ # Make sure that all models return by the relation inherit the relation's
6
+ # scorpion.
7
+ module Relation
8
+ include Scorpion::Stinger
9
+
10
+ # ============================================================================
11
+ # @!group Attributes
12
+ #
13
+
14
+ # @!attribute
15
+ # @return [Scorpion] the scorpion serving the relation.
16
+ attr_accessor :scorpion
17
+
18
+ #
19
+ # @!endgroup Attributes
20
+
21
+ # Elect to use a specific scorpion for all further operations in the
22
+ # chain.
23
+ #
24
+ # @example
25
+ #
26
+ # User.all.with_scorpion( scorpion ).where( ... )
27
+ # User.with_scorpion( scorpion ).where( ... )
28
+ def with_scorpion( scorpion )
29
+ spawn.tap do |other|
30
+ other.scorpion = scorpion
31
+ end
32
+ end
33
+
34
+
35
+ # from ActiveRecord::Relation
36
+ [ :new, :build, :create, :create! ].each do |method|
37
+ class_eval <<-EOS, __FILE__, __LINE__ + 1
38
+ def #{ method }( *args, &block )
39
+ super *args do |*block_args|
40
+ sting!( block_args )
41
+ yield *block_args if block_given?
42
+ end
43
+ end
44
+ EOS
45
+ end
46
+
47
+ # from ActiveRecord::SpawnMethods
48
+ def spawn
49
+ sting!( super )
50
+ end
51
+
52
+ private
53
+ # from ActiveRecord::Relation
54
+ def exec_queries( *args, &block )
55
+ sting!( super )
56
+ end
57
+
58
+ # from ActiveRecord::SpawnMethods
59
+ def relation_with( *args )
60
+ sting!( super )
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,21 @@
1
+ module Scorpion
2
+ module Rails
3
+ module ActiveRecord
4
+ require 'scorpion/rails/active_record/model'
5
+ require 'scorpion/rails/active_record/relation'
6
+ require 'scorpion/rails/active_record/association'
7
+
8
+ # Setup scorpion support for activerecord
9
+ def self.install!
10
+ return unless defined? ::ActiveRecord
11
+
12
+ ::ActiveRecord::Base.send :prepend, Scorpion::Rails::ActiveRecord::Model
13
+ ::ActiveRecord::Relation.send :prepend, Scorpion::Rails::ActiveRecord::Relation
14
+ ::ActiveRecord::Associations::Association.send :prepend, Scorpion::Rails::ActiveRecord::Association
15
+
16
+ # TODO extend Scorpion::Hunter to support AR
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -1,89 +1,49 @@
1
1
  require 'scorpion/nest'
2
- require 'active_support/core_ext/class/attribute'
3
2
 
4
3
  module Scorpion
5
4
  module Rails
6
- # Adds a scorpion nest to rails controllers to automatically support
7
- # injection into rails controllers.
8
- module Controller
9
-
10
- # ============================================================================
11
- # @!group Attributes
12
- #
13
-
14
- # @!attribute
15
- # @return [Scorpion] the scorpion used to fetch dependencies.
16
- attr_reader :scorpion
17
- private :scorpion
18
5
 
19
- # @!attribute
20
- # @return [Scorpion::Nest] the nest used to conceive scorpions.
21
- def nest
22
- self.class.nest
23
- end
24
- private :nest
6
+ # Adds a scorpion nest to support injection into rails controllers.
7
+ module Controller
25
8
 
26
- #
27
- # @!endgroup Attributes
9
+ ENV_KEY = 'scorpion.instance'.freeze
28
10
 
11
+ def scorpion
12
+ env[ENV_KEY]
13
+ end
29
14
 
30
15
  def self.included( base )
31
16
  # Setup dependency injection
32
- base.send :include, Scorpion::King
33
- base.around_action :with_scorpion
34
-
35
- # @!attribute [rw]
36
- # @return [Scorpion::Nest] the singleton nest used by controllers.
37
- base.class_attribute :nest_instance
38
- base.class_exec do
39
-
40
- # @!attribute
41
- # @return [Scorpion::Nest] the nest used to conceive scorpions to
42
- # hunt for objects on each request.
43
- def self.nest
44
- nest_instance
45
- end
46
- def self.nest=( value )
47
- nest_instance.destroy if nest_instance
48
- self.nest_instance = value
49
- end
50
-
51
- # Prepare the nest for conceiving scorpions.
52
- # @see HuntingMap#chart
53
- def self.scorpion_nest( &block )
54
- nest.prepare &block
55
- end
56
- end
57
- base.nest ||= Scorpion.instance.build_nest
58
-
17
+ base.send :include, Scorpion::Rails::Nest
18
+ base.around_filter :with_scorpion
59
19
  super
60
20
  end
61
21
 
62
22
  private
63
23
 
64
24
  # Fetch a scorpion and feed the controller it's dependencies
65
- def with_scorpion( &block )
66
- @scorpion = nest.conceive
25
+ def prepare_scorpion( scorpion )
26
+ scorpion.prepare do |hunter|
27
+ # Allow dependencies to access the controller
28
+ hunter.hunt_for AbstractController::Base, return: self
67
29
 
68
- @scorpion.prepare do |hunter|
69
- hunter.hunt_for AbstractController::Base do
70
- self
71
- end
72
30
  # Allow dependencies to access the current request/response
73
- hunter.hunt_for ActionDispatch::Request do |hunter|
74
- hunter.hunt( AbstractController::Base ).request
31
+ hunter.hunt_for ActionDispatch::Request do |hunt|
32
+ hunt.fetch( AbstractController::Base ).request
75
33
  end
76
- hunter.hunt_for ActionDispatch::Response do |hunter|
77
- hunter.hunt( AbstractController::Base ).response
34
+ hunter.hunt_for ActionDispatch::Response do |hunt|
35
+ hunt.fetch( AbstractController::Base ).response
78
36
  end
79
37
  end
38
+ end
80
39
 
81
- @scorpion.feed self
40
+ def assign_scorpion( scorpion )
41
+ env[ENV_KEY] = scorpion
42
+ end
82
43
 
83
- yield
84
- ensure
85
- @scorpion = nil
44
+ def free_scorpion
86
45
  end
46
+
87
47
  end
88
48
  end
89
49
  end
@@ -0,0 +1,30 @@
1
+ require 'scorpion/nest'
2
+
3
+ module Scorpion
4
+ module Rails
5
+
6
+ # Adds a scorpion nest to support injection into rails background worker jobs.
7
+ module Job
8
+
9
+ def self.included( base )
10
+ # Setup dependency injection
11
+ base.send :include, Scorpion::Rails::Nest
12
+ base.send :around_perform do |job, block|
13
+ job.with_scorpion &block
14
+ end
15
+
16
+ super
17
+ end
18
+
19
+ private
20
+
21
+ def prepare_scorpion( scorpion )
22
+ scorpion.prepare do |hunter|
23
+ hunter.hunt_for ActiveJob::Base do
24
+ self
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,86 @@
1
+ require 'scorpion/nest'
2
+ require 'active_support/core_ext/class/attribute'
3
+
4
+ module Scorpion
5
+ module Rails
6
+ # Handles building a scorpion to handle a single request and populating
7
+ # all the dependencies automatically.
8
+ module Nest
9
+
10
+ # ============================================================================
11
+ # @!group Attributes
12
+ #
13
+
14
+ # @!attribute
15
+ # @return [Scorpion] the scorpion used to fetch dependencies.
16
+ attr_reader :scorpion
17
+ private :scorpion
18
+
19
+ # @!attribute
20
+ # @return [Scorpion::Nest] the nest used to conceive scorpions.
21
+ def nest
22
+ self.class.nest
23
+ end
24
+ private :nest
25
+
26
+ #
27
+ # @!endgroup Attributes
28
+
29
+ def self.included( base )
30
+ # Setup dependency injection
31
+ base.send :include, Scorpion::Object
32
+
33
+ # @!attribute [rw]
34
+ # @return [Scorpion::Nest] the singleton nest used by controllers.
35
+ base.class_attribute :nest_instance
36
+ base.class_exec do
37
+
38
+ # @!attribute
39
+ # @return [Scorpion::Nest] the nest used to conceive scorpions to
40
+ # hunt for objects on each request.
41
+ def self.nest
42
+ nest_instance
43
+ end
44
+ def self.nest=( value )
45
+ nest_instance.destroy if nest_instance
46
+ self.nest_instance = value
47
+ end
48
+
49
+ # Prepare the nest for conceiving scorpions.
50
+ # @see DependencyMap#chart
51
+ def self.scorpion_nest( &block )
52
+ nest.prepare &block
53
+ end
54
+ end
55
+ base.nest ||= Scorpion.instance.build_nest
56
+
57
+ super
58
+ end
59
+
60
+ # Fetch a scorpion and feed the controller it's dependencies, then yield
61
+ # to perform the action within the context of that scorpion.
62
+ def with_scorpion( &block )
63
+ assign_scorpion( nest.conceive )
64
+
65
+ prepare_scorpion( @scorpion ) if respond_to?( :prepare_scorpion, true )
66
+
67
+ hunt = Scorpion::Hunt.new @scorpion, nil, nil
68
+ hunt.inject self
69
+
70
+ yield
71
+ ensure
72
+ free_scorpion
73
+ end
74
+
75
+ private
76
+
77
+ def assign_scorpion( scorpion )
78
+ @scorpion = scorpion
79
+ end
80
+
81
+ def free_scorpion
82
+ @scorpion = nil
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails/railtie'
2
+
3
+ module Scorpion
4
+ module Rails
5
+ class Railtie < ::Rails::Railtie
6
+
7
+ initializer "scorpion.configure" do |app|
8
+ ::ActionController::Base.send :include, Scorpion::Rails::Controller
9
+ ::ActiveJob::Base.send :include, Scorpion::Rails::Job
10
+
11
+ ::Scorpion::Rails::ActiveRecord.install!
12
+ end
13
+
14
+ end
15
+ end
16
+ end