activeconfig 0.5.5
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/Gemfile +7 -0
- data/Rakefile +46 -0
- data/VERSION.yml +5 -0
- data/activeconfig.gemspec +73 -0
- data/bin/active_config +44 -0
- data/lib/active_config.rb +384 -0
- data/lib/active_config/hash_config.rb +213 -0
- data/lib/active_config/hash_weave.rb +72 -0
- data/lib/active_config/suffixes.rb +86 -0
- data/pkg/activeconfig-0.1.4.gem +0 -0
- data/pkg/activeconfig-0.2.0.gem +0 -0
- data/pkg/activeconfig-0.3.0.gem +0 -0
- data/pkg/activeconfig-0.4.0.gem +0 -0
- data/pkg/activeconfig-0.4.1.gem +0 -0
- data/pkg/activeconfig-0.5.0.gem +0 -0
- data/pkg/activeconfig-0.5.1.gem +0 -0
- data/test/active_config_collision_test.rb +40 -0
- data/test/active_config_multi_test.rb +60 -0
- data/test/active_config_test.rb +435 -0
- data/test/active_config_test/global.yml +2 -0
- data/test/active_config_test/test.yml +14 -0
- data/test/active_config_test/test_GB.yml +13 -0
- data/test/active_config_test/test_US.yml +15 -0
- data/test/active_config_test/test_config.yml +0 -0
- data/test/active_config_test/test_local.yml +9 -0
- data/test/active_config_test/test_production.yml +1 -0
- data/test/active_config_test_collision/patha/test.yml +14 -0
- data/test/active_config_test_collision/pathb/test.yml +14 -0
- data/test/active_config_test_collision/pathb/test_local.yml +2 -0
- data/test/active_config_test_multi/patha/test.yml +14 -0
- data/test/active_config_test_multi/pathb/test_local.yml +2 -0
- data/test/env_test.rb +75 -0
- metadata +118 -0
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
|
16
|
+
require 'rubygems'
|
17
|
+
|
18
|
+
#require 'rubygems/package_task'
|
19
|
+
require 'jeweler'
|
20
|
+
Jeweler::Tasks.new do |s|
|
21
|
+
s.name = 'activeconfig'
|
22
|
+
s.author = 'Jeremy Lawler'
|
23
|
+
s.email = 'jeremylawler@gmail.com'
|
24
|
+
s.homepage = 'http://jlawler.github.com/activeconfig/'
|
25
|
+
s.summary = 'An extremely flexible configuration system'
|
26
|
+
s.description = 'An extremely flexible configuration system.
|
27
|
+
s the ability for certain values to be "overridden" when conditions are met.
|
28
|
+
r example, you could have your production API keys only get read when the Rails.env == "production"'
|
29
|
+
s.authors = ["Jeremy Lawler"]
|
30
|
+
end
|
31
|
+
Jeweler::RubygemsDotOrgTasks.new
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
task :rdoc do
|
36
|
+
sh "rm -rf #{File.dirname(__FILE__)}/doc"
|
37
|
+
sh "cd lib && rdoc -o ../doc "
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test do
|
41
|
+
Dir['*/*_test.rb'].each do |f|
|
42
|
+
puts `ruby -I lib #{f}`
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
task :default => :test
|
data/VERSION.yml
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "activeconfig"
|
8
|
+
s.version = "0.5.5"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Jeremy Lawler"]
|
12
|
+
s.date = "2012-05-30"
|
13
|
+
s.description = "An extremely flexible configuration system.\ns the ability for certain values to be \"overridden\" when conditions are met.\nr example, you could have your production API keys only get read when the Rails.env == \"production\""
|
14
|
+
s.email = "jeremylawler@gmail.com"
|
15
|
+
s.executables = ["active_config"]
|
16
|
+
s.files = [
|
17
|
+
"Gemfile",
|
18
|
+
"Rakefile",
|
19
|
+
"VERSION.yml",
|
20
|
+
"activeconfig.gemspec",
|
21
|
+
"bin/active_config",
|
22
|
+
"lib/active_config.rb",
|
23
|
+
"lib/active_config/hash_config.rb",
|
24
|
+
"lib/active_config/hash_weave.rb",
|
25
|
+
"lib/active_config/suffixes.rb",
|
26
|
+
"pkg/activeconfig-0.1.4.gem",
|
27
|
+
"pkg/activeconfig-0.2.0.gem",
|
28
|
+
"pkg/activeconfig-0.3.0.gem",
|
29
|
+
"pkg/activeconfig-0.4.0.gem",
|
30
|
+
"pkg/activeconfig-0.4.1.gem",
|
31
|
+
"pkg/activeconfig-0.5.0.gem",
|
32
|
+
"pkg/activeconfig-0.5.1.gem",
|
33
|
+
"test/active_config_collision_test.rb",
|
34
|
+
"test/active_config_multi_test.rb",
|
35
|
+
"test/active_config_test.rb",
|
36
|
+
"test/active_config_test/global.yml",
|
37
|
+
"test/active_config_test/test.yml",
|
38
|
+
"test/active_config_test/test_GB.yml",
|
39
|
+
"test/active_config_test/test_US.yml",
|
40
|
+
"test/active_config_test/test_config.yml",
|
41
|
+
"test/active_config_test/test_local.yml",
|
42
|
+
"test/active_config_test/test_production.yml",
|
43
|
+
"test/active_config_test_collision/patha/test.yml",
|
44
|
+
"test/active_config_test_collision/pathb/test.yml",
|
45
|
+
"test/active_config_test_collision/pathb/test_local.yml",
|
46
|
+
"test/active_config_test_multi/patha/test.yml",
|
47
|
+
"test/active_config_test_multi/pathb/test_local.yml",
|
48
|
+
"test/env_test.rb"
|
49
|
+
]
|
50
|
+
s.homepage = "http://jlawler.github.com/activeconfig/"
|
51
|
+
s.require_paths = ["lib"]
|
52
|
+
s.rubygems_version = "1.8.11"
|
53
|
+
s.summary = "An extremely flexible configuration system"
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
60
|
+
s.add_development_dependency(%q<bundler>, ["> 1.0.0"])
|
61
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
64
|
+
s.add_dependency(%q<bundler>, ["> 1.0.0"])
|
65
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
66
|
+
end
|
67
|
+
else
|
68
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
69
|
+
s.add_dependency(%q<bundler>, ["> 1.0.0"])
|
70
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
data/bin/active_config
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
=begin rdoc
|
4
|
+
|
5
|
+
# Prints info from to STDOUT.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# > active_config httpd.httpd.domain.portal.primary httpd.httpd.domain.frontend.primary
|
10
|
+
# portal.cashnetusa.com
|
11
|
+
# www.cashnetusa.com
|
12
|
+
#
|
13
|
+
# > ACTIVE_CONFIG_OVERLAY=gb active_config httpd.httpd.domain.portal.primary httpd.httpd.domain.frontend.primary
|
14
|
+
# portaluk.cashnetusa.com
|
15
|
+
# www.quickquid.co.uk
|
16
|
+
#
|
17
|
+
# > ACTIVE_CONFIG_OVERLAY=gb RAILS_ENV=production active_config --PRODDB 'database[RAILS_ENV].database'
|
18
|
+
# PRODDB=activeapp_dev_uk
|
19
|
+
# > ACTIVE_CONFIG_OVERLAY=us RAILS_ENV=production active_config --PRODDB 'database[RAILS_ENV].database'
|
20
|
+
# PRODDB=activeapp_dev
|
21
|
+
|
22
|
+
=end
|
23
|
+
|
24
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + '/lib/ruby')
|
25
|
+
|
26
|
+
require 'rubygems'
|
27
|
+
|
28
|
+
# Yuck!
|
29
|
+
RAILS_ENV = ENV['RAILS_ENV'] || 'development'
|
30
|
+
|
31
|
+
require 'active_config'
|
32
|
+
|
33
|
+
name = ''
|
34
|
+
|
35
|
+
ARGV.each do | x |
|
36
|
+
if x =~ /^--(.+)/
|
37
|
+
name = "#{$1}="
|
38
|
+
else
|
39
|
+
puts(name + (eval(".#{x}").to_s))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
exit 0
|
44
|
+
|
@@ -0,0 +1,384 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'yaml'
|
3
|
+
require 'active_config/hash_weave' # Hash#weave
|
4
|
+
require 'rubygems'
|
5
|
+
require 'active_config/hash_config'
|
6
|
+
require 'active_config/suffixes'
|
7
|
+
require 'erb'
|
8
|
+
|
9
|
+
|
10
|
+
##
|
11
|
+
# See LICENSE.txt for details
|
12
|
+
#
|
13
|
+
#=ActiveConfig
|
14
|
+
#
|
15
|
+
# * Provides dottable, hash, array, and argument access to YAML
|
16
|
+
# configuration files
|
17
|
+
# * Implements multilevel caching to reduce disk accesses
|
18
|
+
# * Overlays multiple configuration files in an intelligent manner
|
19
|
+
#
|
20
|
+
# Config file access example:
|
21
|
+
# Given a configuration file named test.yaml and test_local.yaml
|
22
|
+
# test.yaml:
|
23
|
+
# ...
|
24
|
+
# hash_1:
|
25
|
+
# foo: "foo"
|
26
|
+
# bar: "bar"
|
27
|
+
# bok: "bok"
|
28
|
+
|
29
|
+
# ...
|
30
|
+
# test_local.yaml:
|
31
|
+
# ...
|
32
|
+
# hash_1:
|
33
|
+
# foo: "foo"
|
34
|
+
# bar: "baz"
|
35
|
+
# zzz: "zzz"
|
36
|
+
# ...
|
37
|
+
#
|
38
|
+
# irb> ActiveConfig.test
|
39
|
+
# => {"array_1"=>["a", "b", "c", "d"], "perform_caching"=>true,
|
40
|
+
# "default"=>"yo!", "lazy"=>true, "hash_1"=>{"zzz"=>"zzz", "foo"=>"foo",
|
41
|
+
# "bok"=>"bok", "bar"=>"baz"}, "secure_login"=>true, "test_mode"=>true}
|
42
|
+
#
|
43
|
+
# --Notice that the hash produced is the result of merging the above
|
44
|
+
# config files in a particular order
|
45
|
+
#
|
46
|
+
# The overlay order of the config files is defined by ActiveConfig._get_file_suffixes:
|
47
|
+
# * nil
|
48
|
+
# * _local
|
49
|
+
# * _config
|
50
|
+
# * _local_config
|
51
|
+
# * _{environment} (.i.e _development)
|
52
|
+
# * _{environment}_local (.i.e _development_local)
|
53
|
+
# * _{hostname} (.i.e _whiskey)
|
54
|
+
# * _{hostname}_config_local (.i.e _whiskey_config_local)
|
55
|
+
#
|
56
|
+
# ------------------------------------------------------------------
|
57
|
+
# irb> ActiveConfig.test_local
|
58
|
+
# => {"hash_1"=>{"zzz"=>"zzz", "foo"=>"foo", "bar"=>"baz"}, "test_mode"=>true}
|
59
|
+
#
|
60
|
+
|
61
|
+
class ActiveConfig
|
62
|
+
class ActiveConfig::DuplicateConfig < Exception; end
|
63
|
+
EMPTY_ARRAY = [ ].freeze unless defined? EMPTY_ARRAY
|
64
|
+
def _suffixes
|
65
|
+
@suffixes_obj
|
66
|
+
end
|
67
|
+
# ActiveConfig.new take options from a hash (or hash like) object.
|
68
|
+
# Valid keys are:
|
69
|
+
# :path : Where it can find the config files, defaults to ENV['ACTIVE_CONFIG_PATH'], or RAILS_ROOT/etc
|
70
|
+
# :root_file : Defines the file that holds "top level" configs. (ie active_config.key). Defaults to "global"
|
71
|
+
# :suffixes : Either a suffixes object, or an array of suffixes symbols with their priority. See the ActiveConfig::Suffixes object
|
72
|
+
# :config_refresh : How often we should check for update config files
|
73
|
+
#
|
74
|
+
#
|
75
|
+
#FIXME TODO
|
76
|
+
def initialize opts={}
|
77
|
+
@config_path=opts[:path] || ENV['ACTIVE_CONFIG_PATH'] || (defined?(RAILS_ROOT) ? File.join(RAILS_ROOT,'etc') : nil)
|
78
|
+
@opts=opts
|
79
|
+
if opts[:one_file]
|
80
|
+
@root_file=@config_path
|
81
|
+
else
|
82
|
+
@root_file=opts[:root_file] || 'global'
|
83
|
+
if ActiveConfig::Suffixes===opts[:suffixes]
|
84
|
+
@suffixes_obj = opts[:suffixes]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
@suffixes_obj ||= Suffixes.new self, opts[:suffixes]
|
88
|
+
@suffixes_obj.ac_instance=self
|
89
|
+
@config_refresh =
|
90
|
+
(opts.has_key?(:config_refresh) ? opts[:config_refresh].to_i : 300)
|
91
|
+
@on_load = { }
|
92
|
+
self._flush_cache
|
93
|
+
dups_h=Hash.new{|h,e|h[e]=[]}
|
94
|
+
self._config_path.map{|e|
|
95
|
+
if File.exists?(e) and File.directory?(e)
|
96
|
+
Dir[e + '/*'].map{|f|
|
97
|
+
if File.file?(f)
|
98
|
+
dups_h[File.basename(f)] << f
|
99
|
+
end
|
100
|
+
}
|
101
|
+
else
|
102
|
+
STDERR.puts "WARNING: Active Config Path NOT FOUND #{e}" unless opts[:quiet]
|
103
|
+
end
|
104
|
+
}
|
105
|
+
dups = dups_h.to_a.select{|k,v|v.size>=2}
|
106
|
+
raise ActiveConfig::DuplicateConfig.new(dups.map{|e|"Duplicate file #{e.first} found in \n#{e.last.map{|el|"\t"+el}.join("\n")}"}.join("\n")) if dups.size>0
|
107
|
+
end
|
108
|
+
def _config_path
|
109
|
+
@config_path_ary ||=
|
110
|
+
begin
|
111
|
+
path_sep = (@config_path =~ /;/) ? /;/ : /:/ # Make Wesha happy
|
112
|
+
path = @config_path.split(path_sep).reject{ | x | x.empty? }
|
113
|
+
path.map!{|x| x.freeze }.freeze
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# DON'T CALL THIS IN production.
|
118
|
+
def _flush_cache *types
|
119
|
+
if types.size == 0 or types.include? :hash
|
120
|
+
@cache_hash = { }
|
121
|
+
@hash_times = Hash.new(0)
|
122
|
+
end
|
123
|
+
if types.size == 0 or types.include? :file
|
124
|
+
@file_times = Hash.new(0)
|
125
|
+
@file_cache = { }
|
126
|
+
end
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
def _reload_disabled=(x)
|
131
|
+
@reload_disabled = x.nil? ? false : x
|
132
|
+
end
|
133
|
+
|
134
|
+
def _reload_delay=(x)
|
135
|
+
@config_refresh = x || 300
|
136
|
+
end
|
137
|
+
|
138
|
+
def _verbose=(x)
|
139
|
+
@verbose = x.nil? ? false : x;
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Get each config file's yaml hash for the given config name,
|
144
|
+
# to be merged later. Files will only be loaded if they have
|
145
|
+
# not been loaded before or the files have changed within the
|
146
|
+
# last five minutes, or force is explicitly set to true.
|
147
|
+
#
|
148
|
+
# If file contains the comment:
|
149
|
+
#
|
150
|
+
# # ACTIVE_CONFIG:ERB
|
151
|
+
#
|
152
|
+
# It will be run through ERb before YAML parsing
|
153
|
+
# with the following object bound:
|
154
|
+
#
|
155
|
+
# active_config.config_file => <<the name of the config.yml file>>
|
156
|
+
# active_config.config_directory => <<the directory of the config.yml>>
|
157
|
+
# active_config.config_name => <<the config name>>
|
158
|
+
# active_config.config_files => <<Array of config files to be parsed>>
|
159
|
+
#
|
160
|
+
def _load_config_files(name, force=false)
|
161
|
+
name = name.to_s
|
162
|
+
now = Time.now
|
163
|
+
|
164
|
+
# Get array of all the existing files file the config name.
|
165
|
+
config_files = _config_files(name)
|
166
|
+
|
167
|
+
#$stderr.puts config_files.inspect
|
168
|
+
# Get all the data from all yaml files into as hashes
|
169
|
+
_fire_on_load(name)
|
170
|
+
hashes = config_files.collect do |f|
|
171
|
+
filename=f
|
172
|
+
val=nil
|
173
|
+
mod_time=nil
|
174
|
+
next unless File.exists?(filename)
|
175
|
+
next(@file_cache[filename]) unless (mod_time=File.stat(filename).mtime) != @file_times[filename]
|
176
|
+
begin
|
177
|
+
File.open( filename ) { | yf |
|
178
|
+
val = yf.read
|
179
|
+
}
|
180
|
+
# If file has a # ACTIVE_CONFIG:ERB comment,
|
181
|
+
# Process it as an ERb first.
|
182
|
+
if /^\s*#\s*ACTIVE_CONFIG\s*:\s*ERB/i.match(val)
|
183
|
+
# Prepare a object visible from ERb to
|
184
|
+
# allow basic substitutions into YAMLs.
|
185
|
+
active_config = HashConfig.new({
|
186
|
+
:config_file => filename,
|
187
|
+
:config_directory => File.dirname(filename),
|
188
|
+
:config_name => name,
|
189
|
+
:config_files => config_files,
|
190
|
+
})
|
191
|
+
val = ERB.new(val).result(binding)
|
192
|
+
end
|
193
|
+
# Read file data as YAML.
|
194
|
+
val = YAML::load(val)
|
195
|
+
# STDERR.puts "ActiveConfig: loaded #{filename.inspect} => #{val.inspect}"
|
196
|
+
(@config_file_loaded ||= { })[name] = config_files
|
197
|
+
rescue Exception => e
|
198
|
+
raise
|
199
|
+
end
|
200
|
+
@file_cache[filename]=val
|
201
|
+
@file_times[filename]=mod_time
|
202
|
+
@file_cache[filename]
|
203
|
+
end
|
204
|
+
hashes.compact
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
def get_config_file(name)
|
209
|
+
# STDERR.puts "get_config_file(#{name.inspect})"
|
210
|
+
name = name.to_s # if name.is_a?(Symbol)
|
211
|
+
now = Time.now
|
212
|
+
return @cache_hash[name.to_sym] if
|
213
|
+
(now.to_i - @hash_times[name.to_sym] < @config_refresh)
|
214
|
+
# return cached if we have something cached and no reload_disabled flag
|
215
|
+
return @cache_hash[name.to_sym] if @cache_hash[name.to_sym] and @reload_disabled
|
216
|
+
# $stderr.puts "NOT USING CACHED AND RELOAD DISABLED" if @reload_disabled
|
217
|
+
@cache_hash[name.to_sym]=begin
|
218
|
+
x = _config_hash(name)
|
219
|
+
@hash_times[name.to_sym]=now.to_i
|
220
|
+
x
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
##
|
225
|
+
# Returns a list of all relavant config files as specified
|
226
|
+
# by the suffixes object.
|
227
|
+
def _config_files(name)
|
228
|
+
return [name] if File.exists?(name) and not File.directory?(name)
|
229
|
+
_suffixes.for(name).inject([]) do | files,name_x |
|
230
|
+
_config_path.reverse.inject(files) do |files, dir |
|
231
|
+
files << File.join(dir, name_x.to_s + '.yml')
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def _config_hash(name)
|
237
|
+
unless result = @cache_hash[name]
|
238
|
+
result = @cache_hash[name] =
|
239
|
+
HashConfig._make_indifferent_and_freeze(
|
240
|
+
_load_config_files(name).inject({ }) { | n, h | n.weave(h, false) })
|
241
|
+
end
|
242
|
+
#$stderr.puts result.inspect
|
243
|
+
result
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
##
|
248
|
+
# Register a callback when a config has been reloaded.
|
249
|
+
#
|
250
|
+
# The config :ANY will register a callback for any config file change.
|
251
|
+
#
|
252
|
+
# Example:
|
253
|
+
#
|
254
|
+
# class MyClass
|
255
|
+
# @my_config = { }
|
256
|
+
# ActiveConfig.on_load(:global) do
|
257
|
+
# @my_config = { }
|
258
|
+
# end
|
259
|
+
# def my_config
|
260
|
+
# @my_config ||= something_expensive_thing_on_config(ACTIVEConfig.global.foobar)
|
261
|
+
# end
|
262
|
+
# end
|
263
|
+
#
|
264
|
+
def on_load(*args, &blk)
|
265
|
+
args << :ANY if args.empty?
|
266
|
+
proc = blk.to_proc
|
267
|
+
|
268
|
+
# Call proc on registration.
|
269
|
+
proc.call()
|
270
|
+
|
271
|
+
# Register callback proc.
|
272
|
+
args.each do | name |
|
273
|
+
name = name.to_s
|
274
|
+
(@on_load[name] ||= [ ]) << proc
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
# Do reload callbacks.
|
279
|
+
def _fire_on_load(name)
|
280
|
+
callbacks =
|
281
|
+
(@on_load['ANY'] || EMPTY_ARRAY) +
|
282
|
+
(@on_load[name] || EMPTY_ARRAY)
|
283
|
+
callbacks.uniq!
|
284
|
+
STDERR.puts "_fire_on_load(#{name.inspect}): callbacks = #{callbacks.inspect}" if @verbose && ! callbacks.empty?
|
285
|
+
callbacks.each do | cb |
|
286
|
+
cb.call()
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def _check_config_changed(iname=nil)
|
291
|
+
iname=iname.nil? ? @cache_hash.keys.dup : [*iname]
|
292
|
+
ret=iname.map{ | name |
|
293
|
+
# STDERR.puts "ActiveConfig: config changed? #{name.inspect} reload_disabled = #{@reload_disabled}" if @verbose
|
294
|
+
if config_changed?(name) && ! @reload_disabled
|
295
|
+
STDERR.puts "ActiveConfig: config changed #{name.inspect}" if @verbose
|
296
|
+
if @cache_hash[name]
|
297
|
+
@cache_hash[name] = nil
|
298
|
+
|
299
|
+
# force on_load triggers.
|
300
|
+
name
|
301
|
+
end
|
302
|
+
end
|
303
|
+
}.compact
|
304
|
+
return nil if ret.empty?
|
305
|
+
ret
|
306
|
+
end
|
307
|
+
|
308
|
+
def with_file(name, *args)
|
309
|
+
# STDERR.puts "with_file(#{name.inspect}, #{args.inspect})"; result =
|
310
|
+
args.inject(get_config_file(name)) { | v, i |
|
311
|
+
# STDERR.puts "v = #{v.inspect}, i = #{i.inspect}"
|
312
|
+
case v
|
313
|
+
when Hash
|
314
|
+
v[i.to_s]
|
315
|
+
when Array
|
316
|
+
i.is_a?(Integer) ? v[i] : nil
|
317
|
+
else
|
318
|
+
nil
|
319
|
+
end
|
320
|
+
}
|
321
|
+
# STDERR.puts "with_file(#{name.inspect}, #{args.inspect}) => #{result.inspect}"; result
|
322
|
+
end
|
323
|
+
|
324
|
+
#If you are using this in production code, you fail.
|
325
|
+
def reload(force = false)
|
326
|
+
if force || ! @reload_disabled
|
327
|
+
_flush_cache
|
328
|
+
end
|
329
|
+
nil
|
330
|
+
end
|
331
|
+
|
332
|
+
##
|
333
|
+
# Disables any reloading of config,
|
334
|
+
# executes &block,
|
335
|
+
# calls check_config_changed,
|
336
|
+
# returns result of block
|
337
|
+
#
|
338
|
+
def disable_reload(&block)
|
339
|
+
# This should increment @reload_disabled on entry, decrement on exit.
|
340
|
+
# -- kurt 2007/06/12
|
341
|
+
result = nil
|
342
|
+
reload_disabled_save = @reload_disabled
|
343
|
+
begin
|
344
|
+
@reload_disabled = true
|
345
|
+
result = yield
|
346
|
+
ensure
|
347
|
+
@reload_disabled = reload_disabled_save
|
348
|
+
_check_config_changed unless @reload_disabled
|
349
|
+
end
|
350
|
+
result
|
351
|
+
end
|
352
|
+
|
353
|
+
##
|
354
|
+
# Gets a value from the global config file
|
355
|
+
#
|
356
|
+
def [](key, file=@root_file)
|
357
|
+
get_config_file(file)[key]
|
358
|
+
end
|
359
|
+
|
360
|
+
##
|
361
|
+
# Short-hand access to config file by its name.
|
362
|
+
#
|
363
|
+
# Example:
|
364
|
+
#
|
365
|
+
# ActiveConfig.global(:foo) => ActiveConfig.with_file(:global).foo
|
366
|
+
# ActiveConfig.global.foo => ActiveConfig.with_file(:global).foo
|
367
|
+
#
|
368
|
+
def method_missing(method, *args)
|
369
|
+
return self[method.to_sym] if @opts[:one_file]
|
370
|
+
if method.to_s=~/^_(.*)/
|
371
|
+
_flush_cache
|
372
|
+
return @suffixes.send($1, *args)
|
373
|
+
else
|
374
|
+
if @root_file && rf=get_config_file(@root_file)
|
375
|
+
if rf.has_key?(method.to_sym) || rf.has_key?(method.to_s)
|
376
|
+
return with_file(@root_file).send(method,*args)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
value = with_file(method, *args)
|
380
|
+
value
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|