Class: Micon::Core

Inherits:
Object
  • Object
show all
Defined in:
lib/micon/core.rb

Overview

There are 3 types of component scopes: :application, :instance and custom scope. Custom scopes are managed with ‘activate` and `deactivate` methods.

Instance Attribute Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &block) ⇒ Object (protected)

Generates helper methods, so you can use ‘micon.logger` instead of `micon`



373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/micon/core.rb', line 373

def method_missing m, *args, &block
  super if args.size > 1 or block

  key = m.to_s.sub(/[?=]$/, '').to_sym
  self.class.class_eval do
    define_method key do
      self[key]
    end

    define_method "#{key}=" do |value|
      self[key] = value
    end

    define_method "#{key}?" do
      include? key
    end
  end

  send m, *args
end

Instance Attribute Details

#custom_scopesObject

Scope Management.



6
7
8
# File 'lib/micon/core.rb', line 6

def custom_scopes
  @custom_scopes
end

#metadataObject

Metadata.



152
153
154
# File 'lib/micon/core.rb', line 152

def 
  @metadata
end

Instance Method Details

#[](key) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/micon/core.rb', line 79

def [] key
  sname = @registry[key] || autoload_component_definition(key)

  case sname
  when :instance
    return create_object(key)
  when :application
    o = @application[key]
    unless o
      return create_object(key, @application)
    else
      return o
    end
  else # custom scope.
    container = @custom_scopes[sname]
    raise_without_self "Scope '#{sname}' not started!" unless container
    o = container[key]
    unless o
      return create_object(key, container)
    else
      return o
    end
  end
end

#[]=(key, value) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/micon/core.rb', line 104

def []= key, value
  raise "can't assign nill as :#{key} component!" unless value

  sname = @registry[key] || autoload_component_definition(key)

  value = case sname
  when :instance
    raise_without_self "You can't outject variable with the 'instance' sname!"
  when :application
    @application[key] = value
  else # custom scope.
    container = @custom_scopes[sname]
    raise_without_self "Scope '#{sname}' not started!" unless container
    container[key] = value
  end

  @metadata.call_after key, value

  value
end

#activate(sname, container = {}, &block) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/micon/core.rb', line 8

def activate sname, container = {}, &block
  raise_without_self "Only custom scopes can be activated!" if sname == :application or sname == :instance
  raise "container should have type of Hash but has #{container.class.name}" unless container.is_a? Hash

  raise_without_self "Scope '#{sname}' already active!" if !block and @custom_scopes[sname]

  if block
    begin
      outer_container_or_nil = @custom_scopes[sname]
      @custom_scopes[sname] = container
      @metadata.with_scope_callbacks sname, container, &block
    ensure
      if outer_container_or_nil
        @custom_scopes[sname] = outer_container_or_nil
      else
        @custom_scopes.delete sname
      end
    end
  else
    # not support nested scopes without block
    @custom_scopes[sname] = container
    @metadata.call_before_scope sname, container
  end
end

#active?(sname) ⇒ Boolean

Returns:

  • (Boolean)


43
44
45
46
47
48
49
# File 'lib/micon/core.rb', line 43

def active? sname
  if sname == :application or sname == :instance
    true
  else
    @custom_scopes.include? sname
  end
end

#after(component, options = {}, &block) ⇒ Object



178
179
180
181
182
183
184
185
186
187
# File 'lib/micon/core.rb', line 178

def after component, options = {}, &block
  if include? component
    if options[:bang]
      raise_without_self "component :#{component} already created!"
    else
      block.call self[component]
    end
  end
  @metadata.register_after component, &block
end

#after_scope(sname, options = {}, &block) ⇒ Object



195
196
197
198
199
# File 'lib/micon/core.rb', line 195

def after_scope sname, options = {}, &block
  options[:bang] = true unless options.include? :bang
  raise_without_self "scope :#{sname} already started!" if options[:bang] and active?(sname)
  @metadata.register_after_scope sname, &block
end

#before(component, options = {}, &block) ⇒ Object



173
174
175
176
# File 'lib/micon/core.rb', line 173

def before component, options = {}, &block
  raise_without_self "component :#{component} already created!" if options[:bang] and include?(component)
  @metadata.register_before component, &block
end

#before_scope(sname, options = {}, &block) ⇒ Object



189
190
191
192
193
# File 'lib/micon/core.rb', line 189

def before_scope sname, options = {}, &block
  options[:bang] = true unless options.include? :bang
  raise_without_self "scope :#{sname} already started!" if options[:bang] and active?(sname)
  @metadata.register_before_scope sname, &block
end

#clearObject



51
52
53
54
# File 'lib/micon/core.rb', line 51

def clear
  @application.clear
  @custom_scopes.clear
end

#cloneObject Also known as: deep_clone



201
202
203
204
205
206
207
208
209
210
# File 'lib/micon/core.rb', line 201

def clone
  another = super
  %w(@metadata @application @custom_scopes).each do |name| # @loaded_classes, @constants
    value = instance_variable_get name
    another.instance_variable_set name, value.clone
  end
  another.instance_variable_set '@registry', another..registry
  another.instance_variable_set '@initialized', another.instance_variable_get('@initialized')
  another
end

#deactivate(sname) ⇒ Object



33
34
35
36
37
38
39
40
41
# File 'lib/micon/core.rb', line 33

def deactivate sname
  raise_without_self "Only custom scopes can be deactivated!" if sname == :application or sname == :instance

  raise_without_self "Scope '#{sname}' not active!" unless container = @custom_scopes[sname]

  @metadata.call_after_scope sname, container
  @custom_scopes.delete sname
  container
end

#deinitialize!Object



233
234
235
# File 'lib/micon/core.rb', line 233

def deinitialize!
  Object.send(:remove_const, :MICON) if Object.const_defined?(:MICON)
end

#delete(key) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/micon/core.rb', line 125

def delete key
  sname = @registry[key]

  case sname
  when nil
  when :instance
    raise_without_self "You can't outject variable with the 'instance' scope!"
  when :application
    @application.delete key
  else # custom scope.
    container = @custom_scopes[sname]
    container.delete key if container
  end
end

#delete_all(key) ⇒ Object



140
141
142
143
# File 'lib/micon/core.rb', line 140

def delete_all key
  .delete key
  delete key
end

#development(&block) ⇒ Object



261
# File 'lib/micon/core.rb', line 261

def development █ block.call if development? end

#development?Boolean

Returns:

  • (Boolean)


257
# File 'lib/micon/core.rb', line 257

def development?; mode == :development end

#empty?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/micon/core.rb', line 56

def empty?
  @application.empty? and @custom_scopes.empty?
end

#include?(key) ⇒ Boolean

Component Management.

Returns:

  • (Boolean)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/micon/core.rb', line 62

def include? key
  sname = @registry[key]

  case sname
  when nil
    false
  when :instance
    true
  when :application
    @application.include? key
  else # custom scope.
    container = @custom_scopes[sname]
    return false unless container
    container.include? key
  end
end

#initialize!Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/micon/core.rb', line 213

def initialize!
  unless @initialized
    # Quick access to Metadata inner variable. I intentially broke
    # the Metadata incapsulation to provide better performance, don't refactor it.
    @registry = {}
    @metadata = Micon::Metadata.new(@registry)
    @stack = {}

    @application, @custom_scopes = {}, {}

    @initialized = true
  end

  # Micon::Core is independent itself and there can be multiple Cores simultaneously.
  # But some of its extensions can work only with one global instance, and them need to know how to get it,
  # the MICON constant references this global instance.
  Object.send(:remove_const, :MICON) if Object.const_defined?(:MICON)
  Object.const_set :MICON, self
end

#modeObject

‘mode` used to search for component configuration, examples:

  • ‘app/runtime/logger.production.yml`

  • ‘app/runtime/production/logger.yml`



249
# File 'lib/micon/core.rb', line 249

def mode; @mode ||= :development end

#mode=(mode) ⇒ Object



250
251
252
253
254
# File 'lib/micon/core.rb', line 250

def mode= mode
  mode, force = mode
  raise "some components have been already initialized before You set :mode!" unless empty? or force
  @mode = mode
end

#mode?Boolean

Returns:

  • (Boolean)


255
# File 'lib/micon/core.rb', line 255

def mode?; !!@mode end

#production(&block) ⇒ Object



262
# File 'lib/micon/core.rb', line 262

def production █ block.call if production? end

#production?Boolean

Returns:

  • (Boolean)


258
# File 'lib/micon/core.rb', line 258

def production?; mode == :production end

#raise_without_self(message) ⇒ Object

Raises:

  • (RuntimeError)


265
266
267
# File 'lib/micon/core.rb', line 265

def raise_without_self message
  raise RuntimeError, message, caller.select{|path| path !~ /\/lib\/micon\//}
end

#register(key, options = {}, &initializer) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/micon/core.rb', line 154

def register key, options = {}, &initializer
  raise "key should not be nil or false value!" unless key

  sname = options.delete(:scope) || :application
  dependencies = Array(options.delete(:require) || options.delete(:depends_on))

  raise "unknown options :#{options.keys.join(', :')}!" unless options.empty?

  unless @registry.object_id == @metadata.registry.object_id
    raise "internal error, reference to registry aren't equal to actual registry!"
  end
  @metadata.registry[key] = sname
  @metadata.initializers[key] = [initializer, dependencies]
end

#reset(key) ⇒ Object



145
146
147
148
# File 'lib/micon/core.rb', line 145

def reset key
  delete key
  self[key]
end

#runtime_pathObject

‘runtime_path` is used to search for component configurations, it may be `app/runtime` for example..



238
# File 'lib/micon/core.rb', line 238

def runtime_path; @runtime_path ||= File.expand_path('.') end

#runtime_path=(runtime_path) ⇒ Object



239
240
241
242
243
# File 'lib/micon/core.rb', line 239

def runtime_path= runtime_path
  runtime_path, force = runtime_path
  raise "some components have been already initialized before You set :runtime_path!" unless empty? or force
  @runtime_path = runtime_path
end

#runtime_path?Boolean

Returns:

  • (Boolean)


244
# File 'lib/micon/core.rb', line 244

def runtime_path?; !!@runtime_path end

#test(&block) ⇒ Object



263
# File 'lib/micon/core.rb', line 263

def test █ block.call if test? end

#test?Boolean

Returns:

  • (Boolean)


259
# File 'lib/micon/core.rb', line 259

def test?; mode == :test end

#unregister(key) ⇒ Object



169
170
171
# File 'lib/micon/core.rb', line 169

def unregister key
  @metadata.delete key
end