scorpion-ioc 0.3.1 → 0.4.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.
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