configuration_loader 1.0.0
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/README +47 -0
- data/lib/configuration_loader.rb +183 -0
- data/test/configuration_loader_test.rb +110 -0
- metadata +47 -0
data/README
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
= Configuration Files Loader
|
2
|
+
|
3
|
+
Configuration Files Loader can be used as a gem or a Rails plugin to load various config files.
|
4
|
+
|
5
|
+
It finds config file fragments in a Rails config directory and in config directories of plugins and dependent gems. It then tries to merge them in the following order: gem<-plugin<-application. This allows overrides of global (gem/plugin) configs by individual applications. The supported types for merging are String, Hash, and Array. It caches the content of files by default. ConfigurationLoader is RoR environment aware and provides a shortcut ('load_section') to load a section of a config file corresponding to RAILS_ENV. It is being used in another method provided by ConfigurationLoader - 'load_db_config'. It loads a section from 'config/database.yml' providing a convenient method for placing secondary DB entries in a code as seen here:
|
6
|
+
|
7
|
+
establish_connection ConfigurationLoader.load_db_config['secondary_db']
|
8
|
+
|
9
|
+
See the 'DRYing Up Configuration Files' post in our team blog http://revolutiononrails.blogspot.com/2007/03/drying-up-configuration-files.html for additional details.
|
10
|
+
|
11
|
+
|
12
|
+
== Setup
|
13
|
+
|
14
|
+
=== Installation
|
15
|
+
|
16
|
+
To install Configuration Files Loader as a gem:
|
17
|
+
|
18
|
+
Get the gem file from the project page (http://rubyforge.org/projects/config-loader) and install it
|
19
|
+
|
20
|
+
To install as a Rails plugin:
|
21
|
+
|
22
|
+
ruby script/plugin install svn://rubyforge.org/var/svn/config-loader/trunk/vendor/plugins/configuration_loader
|
23
|
+
|
24
|
+
|
25
|
+
=== Usage
|
26
|
+
|
27
|
+
require 'configuration_loader'
|
28
|
+
|
29
|
+
ConfigurationLoader.load_db_config # gets the RAILS_ENV section from database.yml
|
30
|
+
|
31
|
+
ConfigurationLoader.load('cfg.yml') # loads a YAML-processed config file
|
32
|
+
|
33
|
+
ConfigurationLoader.load('cfg.yml', :erb => true) # loads a ERB+YAML-processed config file
|
34
|
+
|
35
|
+
ConfigurationLoader.load('cfg.yml', :section => RAILS_ENV) # loads a current RAILS_ENV section from a YAML-processed config file
|
36
|
+
|
37
|
+
ConfigLoader.load('cfg.yml', :cache => false) # loads an uncached copy YAML-processed config file
|
38
|
+
|
39
|
+
|
40
|
+
== License
|
41
|
+
|
42
|
+
Configuration Files Loader is released under the MIT license.
|
43
|
+
|
44
|
+
|
45
|
+
== Support
|
46
|
+
|
47
|
+
The RubyForge home page is http://rubyforge.org/projects/config-loader
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# Configuration Files Loader can be used as a gem or a Rails plugin to load config files.
|
2
|
+
#
|
3
|
+
# It finds config file fragments in a rails config directory and in config directories of plugins and dependent gems.
|
4
|
+
# It then tries to merge them in order gem<-plugin<-application thus allowing overrides of global (gem/plugin) configs by individual applications.
|
5
|
+
# The supported types for merging are String, Hash, and Array.
|
6
|
+
#
|
7
|
+
# It caches the content of files by default.
|
8
|
+
#
|
9
|
+
# ConfigurationLoader is RoR environment aware and provides a short-cut 'load_section' to load a section of a config file corresponding to RAILS_ENV.
|
10
|
+
# It is being used in another method provided by ConfigurationLoader - load_db_config.
|
11
|
+
# It loads a section from 'config/database.yml' providing a convenience method for getting secondary DB entries in a code like this:
|
12
|
+
#
|
13
|
+
# establish_connection ConfigurationLoader.load_db_config['secondary_db']
|
14
|
+
#
|
15
|
+
# See the 'DRYing Up Configuration Files' post in our team blog http://revolutiononrails.blogspot.com/2007/03/drying-up-configuration-files.html
|
16
|
+
# for additional details.
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# == Usage
|
20
|
+
#
|
21
|
+
# require 'configuration_loader'
|
22
|
+
#
|
23
|
+
# ConfigurationLoader.load_db_config # gets the RAILS_ENV section from database.yml
|
24
|
+
#
|
25
|
+
# ConfigurationLoader.load('cfg.yml') # loads a YAML-processed config file
|
26
|
+
#
|
27
|
+
# ConfigurationLoader.load('cfg.yml', :erb => true) # loads a ERB+YAML-processed config file
|
28
|
+
#
|
29
|
+
# ConfigurationLoader.load('cfg.yml', :section => RAILS_ENV) # loads a current RAILS_ENV section from a YAML-processed config file
|
30
|
+
#
|
31
|
+
# ConfigLoader.load('cfg.yml', :cache => false) # loads an uncached copy YAML-processed config file
|
32
|
+
#
|
33
|
+
class ConfigurationLoader
|
34
|
+
|
35
|
+
require 'yaml'
|
36
|
+
require 'erb'
|
37
|
+
require 'pp'
|
38
|
+
|
39
|
+
class << self
|
40
|
+
|
41
|
+
@@cached = {}
|
42
|
+
|
43
|
+
# Finds files with a provided file name, loads and processes them. The +options+ control the processing:
|
44
|
+
# :erb => true -- runs the file through ERB before YAML-processing (DEFAULT: false)
|
45
|
+
# :section => 'section_name' -- loads a specific section of the file (like 'development' for 'database.yml') (DEFAULT: nil)
|
46
|
+
# :merge => false -- returns an arrary of processed resulted without trying to merge them into a single entry (DEFAULT: true)
|
47
|
+
# :cache => false -- returns a non-cached copy (DEFAULT: true)
|
48
|
+
def load(file, supplied_options = {})
|
49
|
+
options = default_options.merge(supplied_options)
|
50
|
+
res = load_file(file, options)
|
51
|
+
res = sections(res, options[:section]) if options[:section]
|
52
|
+
res = merge(res) if options[:merge]
|
53
|
+
res
|
54
|
+
end
|
55
|
+
|
56
|
+
# A convenience method for loading the current RAILS_ENV section of the Rails DB config file
|
57
|
+
def load_db_config(section = default_section)
|
58
|
+
load('database.yml', :section => section)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Empties the cached entry[es] thus forcing to reload from a file system next time
|
62
|
+
def refresh!(key = :everything)
|
63
|
+
case key
|
64
|
+
when :everything then
|
65
|
+
@@cached = {}
|
66
|
+
else
|
67
|
+
@@cached.delete(:__configs__)
|
68
|
+
@@cached.delete(key)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def default_options
|
75
|
+
{
|
76
|
+
:erb => false,
|
77
|
+
:section => nil,
|
78
|
+
:merge => true,
|
79
|
+
:cache => true
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_file(file, options)
|
84
|
+
cache(options[:cache])[file] ||= load_yaml_file(file, options)
|
85
|
+
end
|
86
|
+
|
87
|
+
def sections(configs, section)
|
88
|
+
configs.empty? ? nil : collect_sections(configs, section)
|
89
|
+
end
|
90
|
+
|
91
|
+
def collect_sections(configs, section)
|
92
|
+
configs.inject([]) do |config_sections, config|
|
93
|
+
config_sections << config[section] if (config.respond_to?('[]') && config[section])
|
94
|
+
config_sections
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def default_section
|
99
|
+
(defined?(RAILS_ENV) && RAILS_ENV) || 'development'
|
100
|
+
end
|
101
|
+
|
102
|
+
def file_path(path, file)
|
103
|
+
File.join(path, file)
|
104
|
+
end
|
105
|
+
|
106
|
+
def cache(use_cache)
|
107
|
+
use_cache ? @@cached : {}
|
108
|
+
end
|
109
|
+
|
110
|
+
def config_files(use_cache)
|
111
|
+
cache(use_cache)[:__configs__] ||= begin
|
112
|
+
(load_pathes("/gems/") + load_pathes("vendor/plugins/") + app_root).uniq.inject([]) do |configs, path|
|
113
|
+
debug("Component: #{ path }")
|
114
|
+
config = File.join(path, 'config')
|
115
|
+
if File.exist?(config)
|
116
|
+
configs << config
|
117
|
+
debug('Has config')
|
118
|
+
else
|
119
|
+
debug('No config')
|
120
|
+
end
|
121
|
+
configs
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def app_root
|
127
|
+
path = defined?(CONFIG_LOADER_ROOT) ? CONFIG_LOADER_ROOT : RAILS_ROOT
|
128
|
+
[ File.expand_path(path) ]
|
129
|
+
end
|
130
|
+
|
131
|
+
def load_pathes(pattern)
|
132
|
+
$:.grep(%r{#{ pattern }}).collect { |path| File.expand_path(path[%r{.*#{ pattern }[^/]+}]) }
|
133
|
+
end
|
134
|
+
|
135
|
+
def load_yaml_file(file_name, options)
|
136
|
+
config_files(options[:cache]).inject([]) do |loaded, config_path|
|
137
|
+
file = file_path(config_path, file_name)
|
138
|
+
debug("Probing #{ file }")
|
139
|
+
if File.exist?(file)
|
140
|
+
loaded << YAML.load(file_loader(file, options))
|
141
|
+
debug('Found')
|
142
|
+
else
|
143
|
+
debug('Not found')
|
144
|
+
end
|
145
|
+
loaded
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
def file_loader(file, options)
|
151
|
+
res = IO.read(file)
|
152
|
+
res = ERB.new(res).result if options[:erb]
|
153
|
+
res
|
154
|
+
end
|
155
|
+
|
156
|
+
def merge(values)
|
157
|
+
|
158
|
+
debug('Merging configs:') { pp values }
|
159
|
+
|
160
|
+
case
|
161
|
+
when all_are?(values, Hash) then
|
162
|
+
values.inject({}) { |c, v| c.merge(v) }
|
163
|
+
when all_are?(values, Array) then
|
164
|
+
values.inject([]) { |c, v| c + v }
|
165
|
+
else
|
166
|
+
values.last
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
def all_are?(values, type)
|
172
|
+
values.all? { |v| v.is_a?(type) }
|
173
|
+
end
|
174
|
+
|
175
|
+
def debug(msg)
|
176
|
+
if ENV['CONFIG_LOADER_DEBUG']
|
177
|
+
puts "CONFIG_LOADER: #{ msg }"
|
178
|
+
yield if block_given?
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/configuration_loader'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class ConfigurationLoaderTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
::CONFIG_LOADER_ROOT = File.join(File.dirname(__FILE__), 'configs')
|
7
|
+
|
8
|
+
['vendor/plugins', 'gems'].each do |dir|
|
9
|
+
Dir["#{ CONFIG_LOADER_ROOT }/#{ dir }/*"].each { |path| $: << path }
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_default_db_config
|
13
|
+
cfg = ConfigurationLoader.load_db_config
|
14
|
+
assert_not_equal Hash.new, cfg
|
15
|
+
assert cfg['loaded']
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_db_config_section
|
19
|
+
cfg = ConfigurationLoader.load_db_config('test')
|
20
|
+
assert_not_equal Hash.new, cfg
|
21
|
+
assert_equal 'app_db', cfg['db']
|
22
|
+
assert cfg['app_db']
|
23
|
+
assert cfg['plugin_db']
|
24
|
+
assert cfg['gem_db']
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_db_config_unknown_section
|
28
|
+
cfg = ConfigurationLoader.load_db_config('unknown')
|
29
|
+
assert_equal Hash.new, cfg
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_merging_config
|
33
|
+
cfg = ConfigurationLoader.load('cfg.yml')
|
34
|
+
assert cfg['hash']['app']
|
35
|
+
assert_nil cfg['hash']['plugin']
|
36
|
+
assert_nil cfg['hash']['gem']
|
37
|
+
assert_equal [ "app_one", "app_two" ], cfg['array']
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_merging_hash
|
41
|
+
cfg = ConfigurationLoader.load('cfg.yml', :section => 'hash')
|
42
|
+
assert_equal 'app', cfg['global'], 'App takes the precedence among app, plugin, and gem'
|
43
|
+
assert_equal 'plugin', cfg['component'], 'Plugin takes the precedence between plugin and gem'
|
44
|
+
assert cfg['app']
|
45
|
+
assert cfg['plugin']
|
46
|
+
assert cfg['gem']
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_merging_array
|
50
|
+
cfg = ConfigurationLoader.load('cfg.yml', :section => 'array')
|
51
|
+
["app_one", "app_two", "plugin_one", "plugin_two", "gem_one", "gem_two"].each { |e| assert cfg.include?(e) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_merging_string
|
55
|
+
cfg = ConfigurationLoader.load('cfg.yml', :section => 'string')
|
56
|
+
assert_equal 'app', cfg
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_no_merging
|
60
|
+
cfg = ConfigurationLoader.load('cfg.yml', :section => 'string', :merge => false)
|
61
|
+
["app", "plugin", "gem"].each { |e| assert cfg.include?(e) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_erb_processing
|
65
|
+
cfg = ConfigurationLoader.load('cfg.yml')
|
66
|
+
assert_equal '<%= 1 %>', cfg['erb']
|
67
|
+
erb = ConfigurationLoader.load('cfg.yml', :erb => true, :cache => false)
|
68
|
+
assert_equal 1, erb['erb']
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_no_caching
|
72
|
+
|
73
|
+
cfg = ConfigurationLoader.load('cfg.yml')
|
74
|
+
assert_nil cfg['optional']
|
75
|
+
|
76
|
+
add_optional_gem
|
77
|
+
|
78
|
+
cached = ConfigurationLoader.load('cfg.yml')
|
79
|
+
assert_nil cached['optional'], "Still nil since cached"
|
80
|
+
|
81
|
+
fresh = ConfigurationLoader.load('cfg.yml', :cache => false)
|
82
|
+
assert fresh['optional']
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_refresh
|
87
|
+
|
88
|
+
assert_equal Hash.new, ConfigurationLoader.load('optional.yml')
|
89
|
+
cfg = ConfigurationLoader.load('cfg.yml')
|
90
|
+
assert_nil cfg['optional']
|
91
|
+
|
92
|
+
add_optional_gem
|
93
|
+
ConfigurationLoader.refresh!('cfg.yml')
|
94
|
+
|
95
|
+
fresh = ConfigurationLoader.load('cfg.yml', :cache => false)
|
96
|
+
assert fresh['optional']
|
97
|
+
assert_equal Hash.new, ConfigurationLoader.load('optional.yml'), 'Was not refreshed'
|
98
|
+
|
99
|
+
ConfigurationLoader.refresh!
|
100
|
+
assert ConfigurationLoader.load('optional.yml')['loaded']
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def add_optional_gem
|
107
|
+
$: << "#{ CONFIG_LOADER_ROOT }/optional_config/gems/optional_gem"
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: configuration_loader
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2007-03-16 00:00:00 -04:00
|
8
|
+
summary: Configuration files loader
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: rails-trunk@revolution.com
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- RHG Team
|
31
|
+
files:
|
32
|
+
- lib/configuration_loader.rb
|
33
|
+
- README
|
34
|
+
test_files:
|
35
|
+
- test/configuration_loader_test.rb
|
36
|
+
rdoc_options: []
|
37
|
+
|
38
|
+
extra_rdoc_files:
|
39
|
+
- README
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
requirements: []
|
45
|
+
|
46
|
+
dependencies: []
|
47
|
+
|