micon 0.1.16 → 0.1.17
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.
- data/Rakefile +1 -1
- data/lib/micon/config.rb +2 -2
- data/lib/micon/core.rb +52 -52
- data/lib/micon/helper.rb +6 -6
- data/lib/micon/metadata.rb +11 -11
- data/lib/micon/module.rb +9 -9
- data/lib/micon/spec.rb +4 -4
- data/readme.md +168 -75
- data/spec/callbacks_spec.rb +14 -14
- data/spec/config_spec.rb +4 -4
- data/spec/constants_spec.rb +18 -18
- data/spec/custom_scope_spec.rb +9 -9
- data/spec/example_spec/lib/components/controller.rb +8 -0
- data/spec/example_spec/lib/components/logger.production.yml +1 -0
- data/spec/example_spec/lib/components/logger.rb +8 -0
- data/spec/example_spec/lib/components/logger.yml +1 -0
- data/spec/example_spec/lib/components/request.rb +2 -0
- data/spec/example_spec/lib/components/router.rb +12 -0
- data/spec/example_spec/lib/pages_controller.rb +11 -0
- data/spec/example_spec/lib/rack_adapter.rb +25 -0
- data/spec/example_spec/lib/request.rb +8 -0
- data/spec/example_spec.rb +171 -0
- data/spec/initialization_spec.rb +11 -11
- data/spec/managed_spec.rb +3 -3
- data/spec/miscellaneous_spec.rb +11 -11
- data/spec/nested_custom_scope_spec.rb +3 -3
- data/spec/static_scope_spec.rb +11 -11
- metadata +29 -31
- data/spec/overview_spec.rb +0 -67
data/Rakefile
CHANGED
@@ -3,7 +3,7 @@ require 'rake_ext'
|
|
3
3
|
project(
|
4
4
|
name: "micon",
|
5
5
|
gem: true,
|
6
|
-
summary: "
|
6
|
+
summary: "Micon IoC assembles and manages Your Application",
|
7
7
|
|
8
8
|
author: "Alexey Petrushin",
|
9
9
|
homepage: "http://github.com/alexeypetrushin/micon"
|
data/lib/micon/config.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
class Micon::Config
|
1
|
+
class Micon::Config
|
2
2
|
attr_reader :micon, :name
|
3
3
|
def initialize micon, name
|
4
4
|
@micon, @name = micon, name
|
5
5
|
end
|
6
6
|
|
7
|
-
def load
|
7
|
+
def load
|
8
8
|
files = []
|
9
9
|
files.push *config_paths.collect{|path| find_file(path, $LOAD_PATH)}
|
10
10
|
files.push *runtime_config_paths.collect{|path| find_file(path, [micon.runtime_path])} if micon.runtime_path?
|
data/lib/micon/core.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Predefined scopes are: :application | :session | :instance | :"custom_name"
|
2
2
|
#
|
3
3
|
# Micons :"custom_name" are managed by 'scope_begin' / 'scope_end' methods
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# :"custom_name" can't be nested (it will destroy old and start new one) and always should be explicitly started!.
|
6
6
|
class Micon::Core
|
7
7
|
#
|
@@ -27,7 +27,7 @@ class Micon::Core
|
|
27
27
|
@custom_scopes.delete sname
|
28
28
|
end
|
29
29
|
end
|
30
|
-
else
|
30
|
+
else
|
31
31
|
# not support nested scopes without block
|
32
32
|
@custom_scopes[sname] = container
|
33
33
|
@metadata.call_before_scope sname, container
|
@@ -49,10 +49,10 @@ class Micon::Core
|
|
49
49
|
true
|
50
50
|
else
|
51
51
|
@custom_scopes.include? sname
|
52
|
-
end
|
52
|
+
end
|
53
53
|
end
|
54
54
|
|
55
|
-
def clear
|
55
|
+
def clear
|
56
56
|
@application.clear
|
57
57
|
@custom_scopes.clear
|
58
58
|
end
|
@@ -62,9 +62,9 @@ class Micon::Core
|
|
62
62
|
end
|
63
63
|
|
64
64
|
|
65
|
-
#
|
65
|
+
#
|
66
66
|
# Object Management
|
67
|
-
#
|
67
|
+
#
|
68
68
|
def include? key
|
69
69
|
sname = @registry[key]
|
70
70
|
|
@@ -86,21 +86,21 @@ class Micon::Core
|
|
86
86
|
sname = @registry[key] || autoload_component_definition(key)
|
87
87
|
|
88
88
|
case sname
|
89
|
-
when :instance
|
89
|
+
when :instance
|
90
90
|
return create_object(key)
|
91
|
-
when :application
|
92
|
-
o = @application[key]
|
91
|
+
when :application
|
92
|
+
o = @application[key]
|
93
93
|
unless o
|
94
94
|
return create_object(key, @application)
|
95
95
|
else
|
96
96
|
return o
|
97
97
|
end
|
98
|
-
else # custom
|
98
|
+
else # custom
|
99
99
|
container = @custom_scopes[sname]
|
100
100
|
raise_without_self "Scope '#{sname}' not started!" unless container
|
101
101
|
o = container[key]
|
102
102
|
unless o
|
103
|
-
return create_object(key, container)
|
103
|
+
return create_object(key, container)
|
104
104
|
else
|
105
105
|
return o
|
106
106
|
end
|
@@ -122,9 +122,9 @@ class Micon::Core
|
|
122
122
|
raise_without_self "Scope '#{sname}' not started!" unless container
|
123
123
|
container[key] = value
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
@metadata.call_after key, value
|
127
|
-
|
127
|
+
|
128
128
|
value
|
129
129
|
end
|
130
130
|
|
@@ -154,14 +154,14 @@ class Micon::Core
|
|
154
154
|
self[key]
|
155
155
|
end
|
156
156
|
|
157
|
-
#
|
157
|
+
#
|
158
158
|
# Metadata
|
159
|
-
#
|
159
|
+
#
|
160
160
|
attr_accessor :metadata
|
161
161
|
|
162
162
|
def register key, options = {}, &initializer
|
163
163
|
raise "key should not be nil or false value!" unless key
|
164
|
-
options = options.symbolize_keys
|
164
|
+
options = options.symbolize_keys
|
165
165
|
|
166
166
|
sname = options.delete(:scope) || :application
|
167
167
|
dependencies = Array(options.delete(:require) || options.delete(:depends_on))
|
@@ -170,7 +170,7 @@ class Micon::Core
|
|
170
170
|
raise "unknown options :#{options.keys.join(', :')}!" unless options.empty?
|
171
171
|
|
172
172
|
unless @registry.object_id == @metadata.registry.object_id
|
173
|
-
raise "internal error, reference to registry aren't equal to actual registry!"
|
173
|
+
raise "internal error, reference to registry aren't equal to actual registry!"
|
174
174
|
end
|
175
175
|
@metadata.registry[key] = sname
|
176
176
|
@metadata.initializers[key] = [initializer, dependencies] #, constant]
|
@@ -200,11 +200,11 @@ class Micon::Core
|
|
200
200
|
else
|
201
201
|
block.call self[component]
|
202
202
|
end
|
203
|
-
end
|
203
|
+
end
|
204
204
|
@metadata.register_after component, &block
|
205
205
|
end
|
206
206
|
|
207
|
-
def before_scope sname, options = {}, &block
|
207
|
+
def before_scope sname, options = {}, &block
|
208
208
|
options[:bang] = true unless options.include? :bang
|
209
209
|
raise_without_self "scope :#{sname} already started!" if options[:bang] and active?(sname)
|
210
210
|
@metadata.register_before_scope sname, &block
|
@@ -217,7 +217,7 @@ class Micon::Core
|
|
217
217
|
end
|
218
218
|
|
219
219
|
|
220
|
-
|
220
|
+
|
221
221
|
def clone
|
222
222
|
another = super
|
223
223
|
%w(@metadata @application @custom_scopes).each do |name| # @loaded_classes, @constants
|
@@ -226,45 +226,45 @@ class Micon::Core
|
|
226
226
|
end
|
227
227
|
another.instance_variable_set '@registry', another.metadata.registry
|
228
228
|
another.instance_variable_set '@initialized', another.instance_variable_get('@initialized')
|
229
|
-
another
|
229
|
+
another
|
230
230
|
end
|
231
231
|
alias_method :deep_clone, :clone
|
232
232
|
|
233
|
-
def initialize!
|
233
|
+
def initialize!
|
234
234
|
unless @initialized
|
235
235
|
# quick access to Metadata inner variable.
|
236
236
|
# I intentially broke the Metadata incapsulation to provide better performance, don't refactor it.
|
237
237
|
@registry = {} # @loaded_classes, @constants = {}, {}
|
238
238
|
@metadata = Micon::Metadata.new(@registry)
|
239
239
|
@stack = {}
|
240
|
-
|
240
|
+
|
241
241
|
@application, @custom_scopes = {}, {}
|
242
|
-
|
242
|
+
|
243
243
|
@initialized = true
|
244
244
|
end
|
245
|
-
|
246
|
-
# Micon::Core is independent itself and there can be multiple Cores simultaneously.
|
247
|
-
# But some of it's extensions can work only with one global instance, and them need to know how to get it,
|
245
|
+
|
246
|
+
# Micon::Core is independent itself and there can be multiple Cores simultaneously.
|
247
|
+
# But some of it's extensions can work only with one global instance, and them need to know how to get it,
|
248
248
|
# the MICON constant references this global instance.
|
249
249
|
Object.send(:remove_const, :MICON) if Object.const_defined?(:MICON)
|
250
|
-
Object.const_set :MICON, self
|
250
|
+
Object.const_set :MICON, self
|
251
251
|
end
|
252
252
|
|
253
253
|
def deinitialize!
|
254
254
|
Object.send(:remove_const, :MICON) if Object.const_defined?(:MICON)
|
255
|
-
|
255
|
+
|
256
256
|
# @loaded_classes.each do |class_name, tuple|
|
257
257
|
# namespace, const = tuple
|
258
258
|
# namespace.send(:remove_const, const)
|
259
259
|
# end
|
260
260
|
# @loaded_classes.clear
|
261
261
|
end
|
262
|
-
|
263
|
-
#
|
262
|
+
|
263
|
+
#
|
264
264
|
# :mode, :runtime_path, used in component configuration
|
265
265
|
# - 'app/runtime'
|
266
266
|
# - :development, :test, :production
|
267
|
-
#
|
267
|
+
#
|
268
268
|
def runtime_path; @runtime_path || raise(":runtime_path not defined!") end
|
269
269
|
def runtime_path= runtime_path
|
270
270
|
runtime_path, force = runtime_path
|
@@ -272,74 +272,74 @@ class Micon::Core
|
|
272
272
|
@runtime_path = runtime_path
|
273
273
|
end
|
274
274
|
def runtime_path?; !!@runtime_path end
|
275
|
-
|
275
|
+
|
276
276
|
def mode; @mode || raise(":mode not defined!") end
|
277
|
-
def mode= mode
|
278
|
-
mode, force = mode
|
277
|
+
def mode= mode
|
278
|
+
mode, force = mode
|
279
279
|
raise "some components has been already initialized before You set :mode!" unless empty? or force
|
280
280
|
@mode = mode
|
281
281
|
end
|
282
282
|
def mode?; !!@mode end
|
283
283
|
|
284
|
-
protected
|
284
|
+
protected
|
285
285
|
def autoload_component_definition key, bang = true
|
286
286
|
begin
|
287
287
|
require "components/#{key.to_s.gsub(/::/, '/')}"
|
288
288
|
rescue LoadError
|
289
|
-
end
|
289
|
+
end
|
290
290
|
sname = @registry[key]
|
291
291
|
raise_without_self "'#{key}' component not managed!" if bang and !sname
|
292
292
|
sname
|
293
293
|
end
|
294
294
|
|
295
|
-
def create_object key, container = nil
|
295
|
+
def create_object key, container = nil
|
296
296
|
initializer, dependencies, config = @metadata.initializers[key]
|
297
297
|
raise "no initializer for :#{key} component!" unless initializer
|
298
|
-
|
299
|
-
raise "component :#{key} used before it's initialization is finished!" if @stack.include? key
|
298
|
+
|
299
|
+
raise "component :#{key} used before it's initialization is finished!" if @stack.include? key
|
300
300
|
begin
|
301
301
|
dependencies.each{|d| self[d]}
|
302
|
-
@metadata.call_before key
|
302
|
+
@metadata.call_before key
|
303
303
|
|
304
304
|
# we need to check container first, in complex cases (circullar dependency)
|
305
305
|
# the object already may be initialized.
|
306
306
|
# See "should allow to use circullar dependency in :after callback".
|
307
307
|
@stack[key] = true
|
308
308
|
o = (container && container[key]) || initializer.call
|
309
|
-
|
309
|
+
|
310
310
|
unless config == false
|
311
|
-
unless config
|
311
|
+
unless config
|
312
312
|
# loading and caching config
|
313
313
|
config = get_config key
|
314
314
|
config = false unless config # we use false to differentiate from nil
|
315
315
|
@metadata.initializers[key] = [initializer, dependencies, config]
|
316
|
-
|
316
|
+
|
317
317
|
apply_config o, config if config
|
318
318
|
else
|
319
319
|
apply_config o, config
|
320
|
-
end
|
320
|
+
end
|
321
321
|
end
|
322
|
-
|
322
|
+
|
323
323
|
container[key] = o if container
|
324
|
-
|
324
|
+
|
325
325
|
raise "initializer for component :#{key} returns nill!" unless o
|
326
326
|
ensure
|
327
327
|
@stack.delete key
|
328
328
|
end
|
329
|
-
|
329
|
+
|
330
330
|
@metadata.call_after key, o
|
331
|
-
o
|
331
|
+
o
|
332
332
|
end
|
333
|
-
|
333
|
+
|
334
334
|
def get_config key
|
335
335
|
::Micon::Config.new(self, key).load
|
336
336
|
end
|
337
|
-
|
337
|
+
|
338
338
|
def apply_config component, config
|
339
339
|
# config already have keys like "#{k}="
|
340
340
|
config.each{|k, v| component.send(k, v)}
|
341
341
|
end
|
342
|
-
|
342
|
+
|
343
343
|
def name_hack namespace
|
344
344
|
if namespace
|
345
345
|
namespace.to_s.gsub("#<Class:", "").gsub(">", "")
|
data/lib/micon/helper.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
#
|
1
|
+
#
|
2
2
|
# Generates helper methods for Micon,
|
3
3
|
# so you can use micon.config instead of micon[:config]
|
4
4
|
#
|
5
|
-
module Micon::Helper
|
5
|
+
module Micon::Helper
|
6
6
|
def method_missing m, *args, &block
|
7
7
|
super if args.size > 1 or block
|
8
|
-
|
8
|
+
|
9
9
|
key = m.to_s.sub(/[?=]$/, '').to_sym
|
10
10
|
self.class.class_eval do
|
11
11
|
define_method key do
|
12
12
|
self[key]
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
define_method "#{key}=" do |value|
|
16
16
|
self[key] = value
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
define_method "#{key}?" do
|
20
20
|
include? key
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
send m, *args
|
25
25
|
end
|
26
26
|
end
|
data/lib/micon/metadata.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
#
|
2
2
|
# This class intentially made using "wired and not clear code", to provide better performance.
|
3
|
-
#
|
3
|
+
#
|
4
4
|
class Micon::Metadata
|
5
5
|
attr_accessor :registry, :initializers, :before, :after
|
6
6
|
|
@@ -38,9 +38,9 @@ class Micon::Metadata
|
|
38
38
|
alias_method :deep_clone, :clone
|
39
39
|
|
40
40
|
|
41
|
-
#
|
41
|
+
#
|
42
42
|
# Registry
|
43
|
-
#
|
43
|
+
#
|
44
44
|
def [] key
|
45
45
|
@registry[key]
|
46
46
|
end
|
@@ -54,9 +54,9 @@ class Micon::Metadata
|
|
54
54
|
end
|
55
55
|
|
56
56
|
|
57
|
-
#
|
57
|
+
#
|
58
58
|
# Callbacks
|
59
|
-
#
|
59
|
+
#
|
60
60
|
def register_before key, &block
|
61
61
|
raise "you should provide block!" unless block
|
62
62
|
(@before[key] ||= []) << block
|
@@ -69,7 +69,7 @@ class Micon::Metadata
|
|
69
69
|
|
70
70
|
def call_before key
|
71
71
|
if callbacks = @before[key]
|
72
|
-
callbacks.each{|c| c.call}
|
72
|
+
callbacks.each{|c| c.call}
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -80,9 +80,9 @@ class Micon::Metadata
|
|
80
80
|
end
|
81
81
|
|
82
82
|
|
83
|
-
#
|
83
|
+
#
|
84
84
|
# Scope callbacks
|
85
|
-
#
|
85
|
+
#
|
86
86
|
def register_before_scope key, &block
|
87
87
|
raise "you should provide block!" unless block
|
88
88
|
(@before_scope[key] ||= []) << block
|
@@ -113,9 +113,9 @@ class Micon::Metadata
|
|
113
113
|
end
|
114
114
|
|
115
115
|
|
116
|
-
#
|
116
|
+
#
|
117
117
|
# Other
|
118
|
-
#
|
118
|
+
#
|
119
119
|
# def inspect
|
120
120
|
# "Registry: " + self.registry.keys.inspect
|
121
121
|
# end
|
data/lib/micon/module.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
Module.class_eval do
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# inject attribute: :session
|
4
|
-
#
|
4
|
+
#
|
5
5
|
def inject attributes
|
6
6
|
::MICON.raise_without_self "Invalid argument!" unless attributes.is_a? Hash
|
7
7
|
attributes.each do |name, specificator|
|
8
|
-
::MICON.raise_without_self "Attribute name should be a Symbol!" unless name.is_a? Symbol
|
8
|
+
::MICON.raise_without_self "Attribute name should be a Symbol!" unless name.is_a? Symbol
|
9
9
|
|
10
10
|
if [Class, Module].include? specificator.class
|
11
11
|
specificator = specificator.name
|
@@ -28,24 +28,24 @@ def #{name}?
|
|
28
28
|
::MICON.include? #{specificator}
|
29
29
|
end
|
30
30
|
RUBY
|
31
|
-
|
31
|
+
|
32
32
|
self.class_eval script, __FILE__, __LINE__
|
33
33
|
end
|
34
|
-
end
|
34
|
+
end
|
35
35
|
|
36
36
|
|
37
|
-
#
|
37
|
+
#
|
38
38
|
# Hook to use Constants as Components
|
39
|
-
#
|
39
|
+
#
|
40
40
|
# if defined? ::ClassLoader
|
41
41
|
# text = <<-TEXT
|
42
42
|
# It seems that ClassLoader already defined, but it supposed to be activated after the Micon, otherwise it can cause performance loss!
|
43
|
-
# Micon.const_missing extension should be included before than ClassLoader.const_missing otherwise the Micon.const_missing will be
|
43
|
+
# Micon.const_missing extension should be included before than ClassLoader.const_missing otherwise the Micon.const_missing will be
|
44
44
|
# called (and will ping file system) for every loaded class!
|
45
45
|
# TEXT
|
46
46
|
# warn text
|
47
47
|
# end
|
48
|
-
#
|
48
|
+
#
|
49
49
|
# alias_method :const_missing_without_micon, :const_missing
|
50
50
|
# protected :const_missing_without_micon
|
51
51
|
# def const_missing const
|
data/lib/micon/spec.rb
CHANGED
@@ -3,15 +3,15 @@ require 'rspec_ext'
|
|
3
3
|
rspec do
|
4
4
|
def self.with_micon options = {}
|
5
5
|
scope = options[:before] || :all
|
6
|
-
|
6
|
+
|
7
7
|
old, tmp = nil
|
8
|
-
|
9
|
-
before scope do
|
8
|
+
|
9
|
+
before scope do
|
10
10
|
old = MICON
|
11
11
|
tmp = old.clone
|
12
12
|
tmp.initialize!
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
after scope do
|
16
16
|
tmp.deinitialize!
|
17
17
|
old.initialize!
|