Class: Micon::Core

Inherits:
Object
  • Object
show all
Includes:
Helper
Defined in:
lib/micon/core.rb,
lib/micon/support.rb

Overview

Predefined scopes are: :application | :session | :instance | :“custom_name”

Micons :“custom_name” are managed by ‘scope_begin’ / ‘scope_end’ methods

:“custom_name” can’t be nested (it will destroy old and start new one) and always should be explicitly started!.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helper

#method_missing

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Micon::Helper

Instance Attribute Details

#custom_scopesObject

Scope Management



10
11
12
# File 'lib/micon/core.rb', line 10

def custom_scopes
  @custom_scopes
end

#metadataObject

Metadata



220
221
222
# File 'lib/micon/core.rb', line 220

def 
  @metadata
end

Instance Method Details

#[](key) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/micon/core.rb', line 85

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        
    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

def get_constant_component key

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

case sname
when nil
  nil        
when :instance        
  must_be.never_called
when :application        
  return nil unless @constants.include? key

  o = @application[key]          
  unless o
    return create_object(key, @application)
  else
    return o
  end
else # custom        
  must_be.never_called
end

end

def get_constant namespace, const

original_namespace = namespace
namespace = nil if namespace == Object or namespace == Module
target_namespace = namespace

# Name hack (for anonymous classes)
namespace = eval "#{name_hack(namespace)}" if namespace

class_name = namespace ? "#{namespace.name}::#{const}" : const

simple_also_tried = false
begin
  simple_also_tried = (namespace == nil)

  if result = get_constant_component(class_name.to_sym)
    if @loaded_classes.include?(class_name)
      raise_without_self "something wrong is goin on, constant '#{const}' in '#{original_namespace}' namespace already has been defined!"
    end

    real_namespace = namespace ? namespace : Object
    if real_namespace.const_defined?(const)
      raise_without_self "component trying to redefine constant '#{const}' that already defined in '#{real_namespace}'!"
    end

    real_namespace.const_set const, result

    @loaded_classes[class_name] = [real_namespace, const]

    return result
  elsif namespace
    namespace = Module.namespace_for(namespace.name)
    class_name = namespace ? "#{namespace.name}::#{const}" : const
  end
end until simple_also_tried

return nil

end



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/micon/core.rb', line 170

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
    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



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/micon/core.rb', line 12

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)


47
48
49
50
51
52
53
# File 'lib/micon/core.rb', line 47

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

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



255
256
257
258
259
260
261
262
263
264
265
# File 'lib/micon/core.rb', line 255

def after component, options = {}, &block
  options[:bang] = true unless options.include? :bang
  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



273
274
275
276
277
# File 'lib/micon/core.rb', line 273

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



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

def before component, options = {}, &block
  options[:bang] = true unless options.include? :bang
  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



267
268
269
270
271
# File 'lib/micon/core.rb', line 267

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



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

def clear      
  @application.clear
  @custom_scopes.clear
end

#cloneObject Also known as: deep_clone



281
282
283
284
285
286
287
288
289
290
# File 'lib/micon/core.rb', line 281

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



37
38
39
40
41
42
43
44
45
# File 'lib/micon/core.rb', line 37

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



312
313
314
315
316
317
318
319
320
# File 'lib/micon/core.rb', line 312

def deinitialize!
  Object.send(:remove_const, :MICON) if Object.const_defined?(:MICON)
  
  # @loaded_classes.each do |class_name, tuple|
  #   namespace, const = tuple
  #   namespace.send(:remove_const, const)
  # end
  # @loaded_classes.clear
end

#delete(key) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/micon/core.rb', line 191

def delete key
  sname = @registry[key] # || autoload_component_definition(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
    container = @custom_scopes[sname]
    # raise_without_self "Scope '#{sname}' not started!" unless container
    container.delete key if container
  end
end

#delete_all(key) ⇒ Object



207
208
209
210
# File 'lib/micon/core.rb', line 207

def delete_all key
  .delete key
  delete key
end

#empty?Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/micon/core.rb', line 60

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

#include?(key) ⇒ Boolean

Object Management

Returns:

  • (Boolean)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/micon/core.rb', line 68

def include? key
  sname = @registry[key]

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

#initialize!Object



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/micon/core.rb', line 293

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 = {} # @loaded_classes, @constants = {}, {}
    @metadata = Micon::Metadata.new(@registry)
  
    @application, @custom_scopes = {}, {}
    
    @initialized = true
  end
  
  # Micon::Core is independent itself and there can be multiple Cores simultaneously. 
  # But some of it's 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

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



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/micon/core.rb', line 222

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

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

  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] #, constant]
  # if constant
  #   raise "component '#{key}' defined as constant must be a symbol!" unless key.is_a? Symbol
  #   raise "component '#{key}' defined as constant can have only :application scope!" unless sname == :application
  #   @constants[key] = true
  # end
end

#reset(key) ⇒ Object



212
213
214
215
# File 'lib/micon/core.rb', line 212

def reset key
  delete key
  self[key]
end

#unregister(key) ⇒ Object



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

def unregister key
  @metadata.delete key
  # @constants.delete key
end