lib/spontaneous/config.rb
require 'forwardable'
module Spontaneous
class Config
class Loader
attr_reader :settings
def self.read(settings, file, mode)
self.new(settings, file, mode).load
end
def initialize(settings, file = nil, mode = nil)
@settings, @file, @mode = settings, file, mode
end
def load
instance_eval(File.read(@file)) if @file
@settings
end
def back(&block)
__mode__(:back, &block)
end
def front(&block)
__mode__(:front, &block)
end
def __mode__(mode, &block)
if @mode == mode
yield if block_given?
end
end
def method_missing(parameter, *args, &block)
setting = args
if args.length == 1
setting = args[0]
if block_given?
key_name = setting
setting = @settings[parameter] || {}
values = setting[key_name] || {}
block.call(values)
setting.update({ key_name => values })
end
end
@settings[parameter] = setting
end
end
class Configuration
extend ::Forwardable
def initialize(settings = nil)
@settings = {}
merge!(settings) if settings
end
def merge!(hash)
hash.each do |key, value|
add_setting(key, value)
end
end
def []=(key, value)
add_setting(key, value)
end
def add_setting(key, value)
@settings[key] = value
singleton_class.send(:define_method, key) do
value
end
end
def get_setting(key)
v = @settings[key]
if v.is_a?(Proc)
v.call
else
v
end
end
def [](key)
get_setting(key)
end
def method_missing(key, *args)
if key.to_s =~ /=$/
key = key.to_s.gsub(/=$/, '').to_sym
@settings[key] = args[0]
else
if @settings.key?(key)
get_setting(key)
else
# Config.base[key]
nil
end
end
end
def_delegators :@settings, :key?
end
DEFAULTS = {
}.freeze unless defined?(DEFAULTS)
attr_reader :environment, :mode, :env, :base, :local, :defaults
def initialize(environment=:development, mode=:back)
@environment = environment.to_sym
@mode = mode
@local = Configuration.new
@env = Configuration.new
@base = Configuration.new
@defaults = Configuration.new(DEFAULTS)
end
def load(config_root)
default = File.join(config_root, 'environment.rb')
merge_file(default, @base)
file = File.join(config_root, "environments/#{environment}.rb")
merge_file(file, @env)
end
def merge_file(path, configuration)
store = Hash.new
Loader.read(store, path, mode) if File.exist?(path)
configuration.merge!(store)
end
def [](key)
if local.key?(key)
local[key]
elsif env.key?(key)
env[key]
elsif base.key?(key)
base[key]
elsif defaults.key?(key)
defaults[key]
else
# acting like a hash and returning nil for an unknown setting
nil
end
end
def []=(key, val)
local[key] = val
end
def method_missing(key, *args)
if key.to_s =~ /=$/
key = key.to_s.gsub(/=$/, '').to_sym
self[key] = args[0]
else
self[key]
end
end
end
end