Skip to content

Commit

Permalink
add configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
al6x committed Jul 1, 2011
1 parent f80498a commit 9a3803c
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 35 deletions.
3 changes: 3 additions & 0 deletions lib/micon.rb
@@ -1,10 +1,13 @@
require 'yaml'

module Micon
end

%w{
support

metadata
config
core
helper

Expand Down
43 changes: 43 additions & 0 deletions lib/micon/config.rb
@@ -0,0 +1,43 @@
class Micon::Config
attr_reader :micon, :name
def initialize micon, name
@micon, @name = micon, name
end

def load
files = []
files << find_file(config_path(name, nil), $LOAD_PATH)
files << find_file(config_path(name, micon.mode_name), $LOAD_PATH) if micon.mode_name
if micon.runtime_path
files << find_file(runtime_config_path(name, nil), [micon.runtime_path])
files << find_file(runtime_config_path(name, micon.mode_name), [micon.runtime_path]) if micon.mode_name
end

config = {}
files.compact.each do |f|
c = YAML.load_file(f)
next unless c
raise "component config must be a Hash (#{f})!" unless c.is_a? Hash
c.each{|k, v| config[:"#{k}="] = v}
end

config.empty? ? nil : config
end

protected
def config_path name, mode
fs_name = name.to_s.gsub(/::/, '/')
mode ? "/components/#{fs_name}.#{mode}.yml" : "/components/#{fs_name}.yml"
end

def runtime_config_path name, mode
fs_name = name.to_s.gsub(/::/, '/')
mode ? "/config/#{fs_name}.#{mode}.yml" : "/config/#{fs_name}.yml"
end

def find_file path, directories
files = directories.collect{|dir| "#{dir}#{path}"}.select{|f| File.exist? f}
raise "multiple configs for :#{name} component" if files.size > 1
files.first
end
end
70 changes: 37 additions & 33 deletions lib/micon/core.rb
Expand Up @@ -320,6 +320,11 @@ def deinitialize!
# @loaded_classes.clear
end

# override it in Your framework if You need it
# - 'app/runtime'
# - :development, :test, :production
attr_accessor :runtime_path, :mode_name

protected
def autoload_component_definition key, bang = true
begin
Expand All @@ -332,53 +337,52 @@ def autoload_component_definition key, bang = true
end

def create_object key, container = nil
initializer, dependencies = @metadata.initializers[key]
initializer, dependencies, config = @metadata.initializers[key]
raise "no initializer for :#{key} component!" unless initializer

raise "component :#{key} used before it's initialization is finished!" if @stack.include? key
@stack[key] = true
raise "component :#{key} used before it's initialization is finished!" if @stack.include? key
begin
dependencies.each{|d| self[d]}
@metadata.call_before key

if container
unless o = container[key]
o = initializer.call
container[key] = o

# we need to check container first, in complex cases (circullar dependency)
# the object already may be initialized.
# See "should allow to use circullar dependency in :after callback".
@stack[key] = true
o = (container && container[key]) || initializer.call

unless config == false
unless config
# loading and caching config
config = get_config key
config = false unless config # we use false to differentiate from nil
@metadata.initializers[key] = [initializer, dependencies, config]

apply_config o, config if config
else
# complex case, there's an circular dependency, and the 'o' already has been
# initialized in dependecies or callbacks
# here's the sample case:
#
# app.register :environment, :application do
# p :environment
# 'environment'
# end
#
# app.register :conveyors, :application, depends_on: :environment do
# p :conveyors
# 'conveyors'
# end
#
# app.after :environment do
# app[:conveyors]
# end
#
# app[:conveyors]

o = container[key]
end
else
o = initializer.call
apply_config o, config
end
end

container[key] = o if container

raise "initializer for component :#{key} returns nill!" unless o
ensure
@stack.delete key
end

@metadata.call_after key, o
o
end
end

def get_config key
::Micon::Config.new(self, key).load
end

def apply_config component, config
# config already have keys like "#{k}="
config.each{|k, v| component.send(k, v)}
end

def name_hack namespace
if namespace
Expand Down
27 changes: 27 additions & 0 deletions spec/config_spec.rb
@@ -0,0 +1,27 @@
def p; end
require 'spec_helper'

describe "Configuration" do
before{self.micon = Micon::Core.new}
after{micon.runtime_path = nil}

it "should configure component if config provided" do
micon.register(:logger){OpenStruct.new}
with_load_path "#{spec_dir}/basic/lib" do
micon[:logger].level.should == :info
end
end

it "should merge in order: conf <- conf.mode <- runtime <- runtime.mode" do
micon.register(:object){OpenStruct.new}
with_load_path "#{spec_dir}/order/lib" do
micon.runtime_path = "#{spec_dir}/order/app"
micon.mode_name = :production
micon[:object].tap do |o|
o.a.should == 'object.production.yml'
o.b.should == 'runtime.object.yml'
o.c.should == 'runtime.object.production.yml'
end
end
end
end
1 change: 1 addition & 0 deletions spec/config_spec/basic/lib/components/logger.yml
@@ -0,0 +1 @@
level: :info
1 change: 1 addition & 0 deletions spec/config_spec/order/app/config/object.production.yml
@@ -0,0 +1 @@
c: 'runtime.object.production.yml'
2 changes: 2 additions & 0 deletions spec/config_spec/order/app/config/object.yml
@@ -0,0 +1,2 @@
b: 'runtime.object.yml'
c: 'runtime.object.yml'
3 changes: 3 additions & 0 deletions spec/config_spec/order/lib/components/object.production.yml
@@ -0,0 +1,3 @@
a: 'object.production.yml'
b: 'object.production.yml'
c: 'object.production.yml'
3 changes: 3 additions & 0 deletions spec/config_spec/order/lib/components/object.yml
@@ -0,0 +1,3 @@
a: 'object.yml'
b: 'object.yml'
c: 'object.yml'
20 changes: 18 additions & 2 deletions spec/micelaneous_spec.rb
Expand Up @@ -18,7 +18,7 @@
# end
end

describe "complex circullar dependencies" do
describe "complex circullar dependencies" do
it "should not initialize twice (from error)" do
micon.register :kit do
micon[:kit]
Expand All @@ -37,7 +37,7 @@
'router'
end

-> {micon[:router]}.should raise_error(/component :router used before it's initialization is finished/)
-> {micon[:router]}.should raise_error(/component .* used before it's initialization is finished/)
end

it "should allow to use circullar dependency in :after callback" do
Expand All @@ -52,6 +52,22 @@
end
micon[:kit].should == 'kit'
end

it "should allow circullar dependencies in :after callback" do
micon.register :environment do
'environment'
end

micon.register :router, depends_on: :environment do
'router'
end

micon.after :environment do
micon[:router]
end

micon[:router]
end
end

it "helper method generation" do
Expand Down

0 comments on commit 9a3803c

Please sign in to comment.