sugarfree-config 1.1.0 → 2.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/.gitignore +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +22 -0
- data/LICENSE +1 -1
- data/README.rdoc +47 -44
- data/Rakefile +9 -0
- data/lib/sugarfree-config/config.rb +128 -0
- data/lib/sugarfree-config/exceptions.rb +27 -0
- data/lib/sugarfree-config/version.rb +3 -0
- data/lib/sugarfree-config.rb +10 -141
- data/specs/config_spec.rb +155 -0
- data/specs/exceptions_spec.rb +8 -0
- data/specs/spec_helper.rb +9 -0
- data/specs/sugarfree_spec.rb +64 -0
- data/sugarfree-config.gemspec +21 -0
- metadata +59 -41
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sugarfree-config (2.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ansi (1.3.0)
|
10
|
+
metaclass (0.0.1)
|
11
|
+
mocha (0.10.0)
|
12
|
+
metaclass (~> 0.0.1)
|
13
|
+
turn (0.8.2)
|
14
|
+
ansi (>= 1.2.2)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
mocha
|
21
|
+
sugarfree-config!
|
22
|
+
turn
|
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -1,51 +1,64 @@
|
|
1
|
-
=
|
1
|
+
= sugarfree-config
|
2
2
|
|
3
3
|
Configuration handling the easy way.
|
4
4
|
|
5
|
-
|
6
|
-
stored in a YAML file.
|
7
|
-
|
8
|
-
SugarfreeConfig only works with Rails! since SugarfreecConfig 1.1.0 works
|
9
|
-
with rails 3 and ruby 1.9.1
|
5
|
+
sugarfree-config allows easy access to per environment config values
|
6
|
+
stored in a YAML file in Rails and non Rails applications.
|
10
7
|
|
11
8
|
== Installation
|
12
9
|
|
13
|
-
Just install the gem from
|
14
|
-
|
15
|
-
$ gem install sugarfree-config --source http://gemcutter.org
|
16
|
-
|
17
|
-
== Notes on rails 3
|
18
|
-
|
19
|
-
In rails 2.x gems were required after Rails.root was initialized. Default rails 3.0
|
20
|
-
application generator uses Bundler, and auto-requires all gems before application
|
21
|
-
initialization. This could be solved forcing the bundler not to require the gem.
|
22
|
-
In your Gemfile:
|
23
|
-
|
24
|
-
gem 'problematic-gem', :require => false
|
10
|
+
Just install the gem manually from rubygems.org or add it to your bundle.
|
25
11
|
|
26
|
-
|
27
|
-
|
28
|
-
require 'problematic-gem'
|
12
|
+
$ gem install sugarfree-config
|
29
13
|
|
30
14
|
== Usage
|
31
15
|
|
32
|
-
|
33
|
-
at least a section for each RAILS_ENV
|
34
|
-
|
35
|
-
Configuration can be accessed like this
|
16
|
+
Configuration can be accessed using method calls:
|
36
17
|
|
37
18
|
SugarfreeConfig.a.b.c #=> 'value'
|
38
19
|
|
39
|
-
which will expect a config file like (given development env)
|
20
|
+
which will expect a config.yml file like the one below (given development env)
|
21
|
+
stored in the config folder (in Rails apps) or the root folder (in non Rails apps):
|
40
22
|
|
41
23
|
development:
|
42
24
|
a:
|
43
25
|
b:
|
44
26
|
c: 'value'
|
45
27
|
|
46
|
-
|
28
|
+
If asking for akey that does not exists ConfigKeyException will be raised.
|
29
|
+
|
30
|
+
A convinience to_hash method is also provided:
|
31
|
+
|
32
|
+
SugarfreeConfig.a.to_hash #=> { 'b' => { 'c' => 'value' } }
|
33
|
+
|
34
|
+
== Configuration
|
47
35
|
|
48
|
-
|
36
|
+
sugarfree-config can be used with or without Rails. Default configurations are
|
37
|
+
provided for each case. Default configurations can be overriden the explicit use
|
38
|
+
of the SugarfreeConfig::init method.
|
39
|
+
|
40
|
+
To set the configuration you need to initialize the SugarfreeConfig class:
|
41
|
+
|
42
|
+
SugarfreeConfig.init :env => 'development', :file => 'my_config.yml', :reload => true
|
43
|
+
|
44
|
+
# Default options in Rails apps
|
45
|
+
SugarfreeConfig.init({
|
46
|
+
:env => Rails.env,
|
47
|
+
:file => Rails.root.join('config', 'config.yml'),
|
48
|
+
:reload => Rails.env.development?
|
49
|
+
})
|
50
|
+
|
51
|
+
# Default options in non Rails apps
|
52
|
+
SugarfreeConfig.init({
|
53
|
+
:env => 'development',
|
54
|
+
:file => File.expand_path('config.yml'),
|
55
|
+
:reload => false
|
56
|
+
})
|
57
|
+
|
58
|
+
|
59
|
+
== Gotchas
|
60
|
+
|
61
|
+
Configuration is accessed through a ConfigIterator class which (as its name says) is
|
49
62
|
an iterator and cannot be reused. However there is a workaround to allow the
|
50
63
|
repeated use of scoped iterators.
|
51
64
|
|
@@ -59,25 +72,15 @@ repeated use of scoped iterators.
|
|
59
72
|
a_config.dup.b.c #=> 'value'
|
60
73
|
a_config.dup.b.c #=> 'value'
|
61
74
|
|
62
|
-
== Further customization
|
63
|
-
|
64
|
-
By default Sugarfree-config caches in memory the YAML file. If you want the gem
|
65
|
-
to reload this file each time a value is accessed (like in development mode)
|
66
|
-
you must force the initialization of the SugarfreeConfig module.
|
67
75
|
|
68
|
-
|
76
|
+
== Compatibility
|
69
77
|
|
70
|
-
|
71
|
-
|
72
|
-
class Object
|
73
|
-
# For people who prefer app_config.a.b.c instead of SugarfreeConfig.a.b.c
|
74
|
-
def app_config
|
75
|
-
SugarfreeConfig
|
76
|
-
end
|
77
|
-
end
|
78
|
+
SugarfreeConfig 2.0.0 has been developed and tested against Ruby 1.9.2 and Rails 3.x.
|
79
|
+
Older versions of Ruby and Rails may also work. Just give it a try ;)
|
78
80
|
|
79
81
|
== Contact
|
80
82
|
|
81
|
-
Please
|
82
|
-
|
83
|
+
Please use GitHub (https://github.com/davidbarral/sugarfree-config) to report bugs,
|
84
|
+
make suggestions or send patches.
|
85
|
+
|
83
86
|
|
data/Rakefile
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module SugarfreeConfig
|
4
|
+
|
5
|
+
#
|
6
|
+
# Config base object. Caches the configuration in memory an acts as a factory
|
7
|
+
# for the ConfigIterators needed to get config values
|
8
|
+
#
|
9
|
+
class Config
|
10
|
+
|
11
|
+
#
|
12
|
+
# Creates a new config object and load the config file into memory
|
13
|
+
#
|
14
|
+
def initialize(options)
|
15
|
+
options = default_options.merge(options)
|
16
|
+
|
17
|
+
@file = options[:file]
|
18
|
+
@reload = options[:reload]
|
19
|
+
@env = options[:env]
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Returns all the config as a big hash
|
24
|
+
#
|
25
|
+
def to_hash
|
26
|
+
values
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Here is the magic. The first request to config returns a new
|
31
|
+
# ConfigIterator that will handle the first +symbol+
|
32
|
+
#
|
33
|
+
def method_missing(symbol, *args)
|
34
|
+
ConfigIterator.new(values, symbol).next
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def values
|
40
|
+
@config = fetch_config unless @config && !@reload
|
41
|
+
@config
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Fetch the config from the file
|
46
|
+
#
|
47
|
+
def fetch_config
|
48
|
+
Rails.logger.debug "Loading #{@file}::#{@env}" if Object.const_defined?('Rails')
|
49
|
+
YAML::load_file(@file)[@env.to_s]
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Default configuration options for Rails and non Rails applications
|
54
|
+
#
|
55
|
+
def default_options
|
56
|
+
if Object.const_defined?('Rails')
|
57
|
+
{
|
58
|
+
:file => Rails.root.join('config', 'config.yml'),
|
59
|
+
:reload => Rails.env.development?,
|
60
|
+
:env => Rails.env
|
61
|
+
}
|
62
|
+
else
|
63
|
+
{
|
64
|
+
:file => File.expand_path("config.yml"),
|
65
|
+
:reload => false,
|
66
|
+
:env => "development"
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Config Iterator. Given a configuration hash it can navigate trough the
|
74
|
+
# values using method calls that will be translated into hash keys and
|
75
|
+
# indexed
|
76
|
+
#
|
77
|
+
class ConfigIterator
|
78
|
+
|
79
|
+
#
|
80
|
+
# Create a new iterator with a given +configuration+ and the first
|
81
|
+
# element of the path to be iterated (+first_path_element+)
|
82
|
+
#
|
83
|
+
def initialize(configuration, first_path_element)
|
84
|
+
@scoped_config = configuration
|
85
|
+
@path_elements = [first_path_element.to_s]
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Returns the current scope as a hash. Usefull to get a Big hash of config
|
90
|
+
# that will be used later.
|
91
|
+
#
|
92
|
+
def to_hash
|
93
|
+
@scoped_config
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Here is the magic. When an unknown symbol is passed this symbol is set
|
98
|
+
# as the last path element of this iteration, and the iterator is then
|
99
|
+
# forced to make that movement
|
100
|
+
#
|
101
|
+
def method_missing(symbol, *args)
|
102
|
+
@path_elements << symbol.to_s
|
103
|
+
self.next
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Iterate to the next element in the path
|
108
|
+
#
|
109
|
+
# Algorithm:
|
110
|
+
# 1. Get the last element of the key path
|
111
|
+
# 2. Try to find it in the scoped config
|
112
|
+
# 3. If not present raise an error
|
113
|
+
# 4. If present and is a hash we are not in a config leaf, so the scoped
|
114
|
+
# config is reset to this new value and self is returned
|
115
|
+
# 5. If present and is a value then return the value
|
116
|
+
#
|
117
|
+
def next
|
118
|
+
if (value = @scoped_config[@path_elements.last]).nil?
|
119
|
+
raise ConfigKeyException.new(@path_elements)
|
120
|
+
elsif value.is_a?(Hash)
|
121
|
+
@scoped_config = value
|
122
|
+
self
|
123
|
+
else
|
124
|
+
value
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SugarfreeConfig
|
2
|
+
#
|
3
|
+
# Exception raised by the module on unexpected behaviors
|
4
|
+
#
|
5
|
+
class ConfigException < Exception
|
6
|
+
end
|
7
|
+
|
8
|
+
#
|
9
|
+
# Exception raised by the Config Iterator when a key is not found
|
10
|
+
#
|
11
|
+
class ConfigKeyException < ConfigException
|
12
|
+
|
13
|
+
#
|
14
|
+
# Config key path (as a key collection) that failed
|
15
|
+
#
|
16
|
+
attr_accessor :key_path_elements
|
17
|
+
|
18
|
+
#
|
19
|
+
# Create a new exception with the not found key paths (+key_path_elements+
|
20
|
+
# Array)
|
21
|
+
#
|
22
|
+
def initialize(key_path_elements)
|
23
|
+
self.key_path_elements = [*key_path_elements].map(&:to_s)
|
24
|
+
super("Cannot find key #{self.key_path_elements.join('.')}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/sugarfree-config.rb
CHANGED
@@ -1,155 +1,24 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
require 'sugarfree-config/exceptions'
|
3
|
+
require 'sugarfree-config/config'
|
4
|
+
|
2
5
|
# Sugarfree config allows easy access to the config values.
|
3
6
|
#
|
4
|
-
# See README.
|
7
|
+
# See README.rdoc for usage info
|
5
8
|
#
|
6
9
|
module SugarfreeConfig
|
7
10
|
|
8
11
|
class << self
|
9
12
|
attr_reader :config
|
10
|
-
def init(force_reload = false)
|
11
|
-
@config = Config.new(force_reload)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.method_missing(*args)
|
16
|
-
init unless SugarfreeConfig.config
|
17
|
-
SugarfreeConfig.config.send(*args)
|
18
|
-
end
|
19
|
-
|
20
|
-
#
|
21
|
-
# Exception raised by the module on unexpected behaviors
|
22
|
-
#
|
23
|
-
class ConfigException < Exception
|
24
|
-
end
|
25
13
|
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
class ConfigKeyException < ConfigException
|
30
|
-
|
31
|
-
#
|
32
|
-
# Config key path (as a key collection) that failed
|
33
|
-
#
|
34
|
-
attr_accessor :key_path_elements
|
35
|
-
|
36
|
-
#
|
37
|
-
# Create a new exception with the not found key paths (+key_path_elements+
|
38
|
-
# Array)
|
39
|
-
#
|
40
|
-
def initialize(key_path_elements)
|
41
|
-
self.key_path_elements = [*key_path_elements].map(&:to_s)
|
42
|
-
super("Cannot find key #{self.key_path_elements.join('.')}")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
#
|
47
|
-
# Config base object. Caches the configuration in memory an acts as a factory
|
48
|
-
# for the ConfigIterators needed to get config values
|
49
|
-
#
|
50
|
-
class Config
|
51
|
-
|
52
|
-
#
|
53
|
-
# Conifg file is expected at "#{RAILS_ROOT}/config/config.yml"
|
54
|
-
#
|
55
|
-
DEFAULT_CONFIG_FILE = Rails.root.join('config', 'config.yml')
|
56
|
-
|
57
|
-
def values
|
58
|
-
@values = fetch_config unless @values && !@force_reload
|
59
|
-
@values
|
14
|
+
def init(options = {})
|
15
|
+
@config = Config.new(options)
|
60
16
|
end
|
61
17
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
def initialize(force_reload = false)
|
66
|
-
@force_reload = force_reload
|
67
|
-
end
|
68
|
-
|
69
|
-
#
|
70
|
-
# Returns all the config as a big hash
|
71
|
-
#
|
72
|
-
def to_hash
|
73
|
-
@values
|
74
|
-
end
|
75
|
-
|
76
|
-
#
|
77
|
-
# Here is the magic. The first request to config returns a new
|
78
|
-
# ConfigIterator that will handle the first +symbol+
|
79
|
-
#
|
80
|
-
def method_missing(symbol, *args)
|
81
|
-
ConfigIterator.new(values, symbol).next
|
82
|
-
end
|
83
|
-
|
84
|
-
protected
|
85
|
-
|
86
|
-
#
|
87
|
-
# Fetch the config from the file
|
88
|
-
#
|
89
|
-
def fetch_config
|
90
|
-
if Object.const_defined?('RAILS_DEFAULT_LOGGER') && RAILS_DEFAULT_LOGGER.debug?
|
91
|
-
RAILS_DEFAULT_LOGGER.debug "Loading #{DEFAULT_CONFIG_FILE}::#{RAILS_ENV}"
|
92
|
-
end
|
93
|
-
HashWithIndifferentAccess.new(YAML::load(File.new(DEFAULT_CONFIG_FILE))[RAILS_ENV])
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
#
|
98
|
-
# Config Iterator. Given a configuration hash it can navigate trough the
|
99
|
-
# values using method calls that will be translated into hash keys and
|
100
|
-
# indexed
|
101
|
-
#
|
102
|
-
class ConfigIterator
|
103
|
-
|
104
|
-
#
|
105
|
-
# Create a new iterator with a given +configuration+ and the first
|
106
|
-
# element of the path to be iterated (+first_path_element+)
|
107
|
-
#
|
108
|
-
def initialize(configuration, first_path_element)
|
109
|
-
@scoped_config = configuration
|
110
|
-
@path_elements = [first_path_element]
|
111
|
-
end
|
112
|
-
|
113
|
-
#
|
114
|
-
# Returns the current scope as a hash. Usefull to get a Big hash of config
|
115
|
-
# that will be used later.
|
116
|
-
#
|
117
|
-
def to_hash
|
118
|
-
@scoped_config
|
119
|
-
end
|
120
|
-
|
121
|
-
#
|
122
|
-
# Iterate to the next element in the path
|
123
|
-
#
|
124
|
-
# Algorithm:
|
125
|
-
# 1. Get the last element of the key path
|
126
|
-
# 2. Try to find it in the scoped config.
|
127
|
-
# 3. If not present raise an error
|
128
|
-
# 4. If present and is a hash we are not in a config leaf, so the scoped
|
129
|
-
# config is reset to this new value and self is returned
|
130
|
-
# 5. If present and is a value then return the value
|
131
|
-
#
|
132
|
-
def next
|
133
|
-
if (value = @scoped_config[@path_elements.last]).nil?
|
134
|
-
raise ConfigKeyException.new(@path_elements)
|
135
|
-
elsif value.is_a?(Hash)
|
136
|
-
@scoped_config = value
|
137
|
-
self
|
138
|
-
else
|
139
|
-
value
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
#
|
144
|
-
# Here is the magic. When an unknown symbol is passed this symbol is set
|
145
|
-
# as the last path element of this iteration, and the iterator is then
|
146
|
-
# forced to make that movement
|
147
|
-
#
|
148
|
-
def method_missing(symbol, *args)
|
149
|
-
@path_elements << symbol
|
150
|
-
self.next
|
18
|
+
def method_missing(*args)
|
19
|
+
init unless SugarfreeConfig.config
|
20
|
+
SugarfreeConfig.config.send(*args)
|
151
21
|
end
|
152
22
|
end
|
153
|
-
|
154
23
|
end
|
155
24
|
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Config" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@config = {
|
7
|
+
'an_env' => {
|
8
|
+
'l1' => {
|
9
|
+
'l2' => 'a'
|
10
|
+
}
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "initialize with no params for non rails apps" do
|
16
|
+
it "should return default values" do
|
17
|
+
Object.stubs(:const_defined?).with('Rails').returns(false)
|
18
|
+
h = mock()
|
19
|
+
h.expects(:'[]').with('development').once().returns({})
|
20
|
+
YAML.expects(:load_file).with(File.expand_path("config.yml")).once().returns(h)
|
21
|
+
|
22
|
+
c = SugarfreeConfig::Config.new({})
|
23
|
+
c.to_hash
|
24
|
+
c.to_hash
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "initialize with no params for rails apps" do
|
29
|
+
|
30
|
+
#
|
31
|
+
# Yehaaaa! I know it's awful
|
32
|
+
#
|
33
|
+
it "should return default values" do
|
34
|
+
Object.stubs(:const_defined?).with('Rails').returns(true)
|
35
|
+
|
36
|
+
rails_root = mock()
|
37
|
+
rails_root.expects(:join).once().with('config', 'config.yml').returns("/rails_root/config/config.yml")
|
38
|
+
|
39
|
+
rails_logger = mock()
|
40
|
+
rails_logger.expects(:debug).once().with("Loading /rails_root/config/config.yml::production")
|
41
|
+
|
42
|
+
String.any_instance.stubs(:development?).returns(false)
|
43
|
+
|
44
|
+
Rails = mock()
|
45
|
+
Rails.stubs(:root).returns(rails_root)
|
46
|
+
Rails.stubs(:env).returns("production")
|
47
|
+
Rails.stubs(:logger).returns(rails_logger)
|
48
|
+
|
49
|
+
h = mock()
|
50
|
+
h.expects(:'[]').with('production').once().returns({})
|
51
|
+
YAML.expects(:load_file).with("/rails_root/config/config.yml").once.returns(h)
|
52
|
+
|
53
|
+
c = SugarfreeConfig::Config.new({})
|
54
|
+
c.to_hash
|
55
|
+
c.to_hash
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "reloading" do
|
60
|
+
it "should reload the configuration if set to" do
|
61
|
+
Object.stubs(:const_defined?).with('Rails').returns(false)
|
62
|
+
YAML.expects(:load_file).twice().returns(@config)
|
63
|
+
|
64
|
+
c = SugarfreeConfig::Config.new(:reload => true, :env => 'an_env')
|
65
|
+
c.to_hash
|
66
|
+
c.to_hash
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not reload the configuration" do
|
70
|
+
Object.stubs(:const_defined?).with('Rails').returns(false)
|
71
|
+
YAML.expects(:load_file).once.returns(@config)
|
72
|
+
|
73
|
+
SugarfreeConfig::Config.new(:reload => false, :env => 'an_env').to_hash
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "to_hash" do
|
78
|
+
it "should return the base config for a given env" do
|
79
|
+
Object.stubs(:const_defined?).with('Rails').returns(false)
|
80
|
+
YAML.stubs(:load_file).returns(@config)
|
81
|
+
|
82
|
+
c = SugarfreeConfig::Config.new(:env => 'an_env')
|
83
|
+
c.to_hash.must_equal @config['an_env']
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "method_missing" do
|
88
|
+
it "should return an scoped iterator config" do
|
89
|
+
Object.stubs(:const_defined?).with('Rails').returns(false)
|
90
|
+
YAML.stubs(:load_file).returns(@config)
|
91
|
+
|
92
|
+
c = SugarfreeConfig::Config.new(:env => 'an_env')
|
93
|
+
ci = c.l1
|
94
|
+
ci.must_be_instance_of SugarfreeConfig::ConfigIterator
|
95
|
+
ci.to_hash.must_equal @config['an_env']['l1']
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
describe "ConfigIterator" do
|
102
|
+
|
103
|
+
before do
|
104
|
+
@config = {
|
105
|
+
'l1' => {
|
106
|
+
'l2a' => {
|
107
|
+
'l3' => 'a'
|
108
|
+
},
|
109
|
+
'l2b' => 'b'
|
110
|
+
}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def iterator(config,key)
|
115
|
+
SugarfreeConfig::ConfigIterator.new(config, key)
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
describe "to_hash" do
|
120
|
+
it "should return the scoped config" do
|
121
|
+
ci = iterator(@config, :l1)
|
122
|
+
|
123
|
+
ci.to_hash.must_equal @config
|
124
|
+
ci.next.to_hash.must_equal @config['l1']
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "method_missing" do
|
129
|
+
it "should move the iterator" do
|
130
|
+
ci = iterator(@config, :l1)
|
131
|
+
ci.to_hash.wont_equal ci.next.to_hash
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "next" do
|
137
|
+
|
138
|
+
it "should raise an exception when key is not available" do
|
139
|
+
ci = iterator(@config, :unknown_key)
|
140
|
+
lambda { ci.next }.must_raise SugarfreeConfig::ConfigKeyException
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should return a value if iterated node is a leaf" do
|
144
|
+
iterator(@config['l1'], :l2b).next.must_equal 'b'
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should return self and change iterator state if iterated node is not leaf" do
|
148
|
+
ci = iterator(@config, :l1)
|
149
|
+
cii = ci.next
|
150
|
+
cii.must_be_same_as ci
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "ConfigKeyException" do
|
4
|
+
it "keeps the path elements that caused the exception as a String array" do
|
5
|
+
SugarfreeConfig::ConfigKeyException.new(:el1).key_path_elements.must_equal(["el1"])
|
6
|
+
SugarfreeConfig::ConfigKeyException.new([:el1, :el2]).key_path_elements.must_equal(["el1", "el2"])
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "SugarfreeConfig" do
|
4
|
+
|
5
|
+
describe "config" do
|
6
|
+
it "should create a Config with the given options" do
|
7
|
+
opts = { :o1 => 2, :o2 => 2 }
|
8
|
+
SugarfreeConfig::Config.expects(:new).once().with(opts)
|
9
|
+
SugarfreeConfig.init(opts)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "method_missing" do
|
14
|
+
it "should create a Config and delegate" do
|
15
|
+
config = mock()
|
16
|
+
config.expects(:send).with(:test1)
|
17
|
+
config.expects(:send).with(:test2)
|
18
|
+
SugarfreeConfig::Config.expects(:new).once().returns(config)
|
19
|
+
|
20
|
+
SugarfreeConfig.test1
|
21
|
+
SugarfreeConfig.test2
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
describe "SugarfreeConfig delegation" do
|
28
|
+
|
29
|
+
before do
|
30
|
+
@config = {
|
31
|
+
'development' => {
|
32
|
+
'simple_config_key' => 1234,
|
33
|
+
'nested_config_keys' => {
|
34
|
+
'nested_key' => "the nested key"
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
YAML.stubs(:load_file).returns(@config)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "to_hash" do
|
43
|
+
it "should return the environment config as a hash" do
|
44
|
+
SugarfreeConfig.to_hash.must_equal(@config['development'])
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should honor the scope" do
|
48
|
+
SugarfreeConfig.nested_config_keys.to_hash.must_equal(@config['development']['nested_config_keys'])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "asking for keys" do
|
53
|
+
|
54
|
+
it "should return the configuration values" do
|
55
|
+
SugarfreeConfig.simple_config_key.must_equal 1234
|
56
|
+
SugarfreeConfig.nested_config_keys.nested_key.must_equal 'the nested key'
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should fail when aksing for non existent key" do
|
60
|
+
lambda { SugarfreeConfig.non_existent_key }.must_raise SugarfreeConfig::ConfigKeyException
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "sugarfree-config/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sugarfree-config"
|
7
|
+
s.version = SugarfreeConfig::VERSION
|
8
|
+
s.authors = ["David Barral"]
|
9
|
+
s.email = ["contact@davidbarral.com"]
|
10
|
+
s.homepage = "http://github.com/davidbarral/sugarfree-config"
|
11
|
+
s.summary = "Configuration handling the easy way"
|
12
|
+
s.description = "Access to per Rails environment configuration stored in a YAML file"
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_development_dependency('mocha')
|
20
|
+
s.add_development_dependency('turn')
|
21
|
+
end
|
metadata
CHANGED
@@ -1,65 +1,83 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: sugarfree-config
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 1
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
version: 1.1.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- David Barral
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
date: 2011-10-04 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mocha
|
16
|
+
requirement: &20817940 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *20817940
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: turn
|
27
|
+
requirement: &20817520 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *20817520
|
21
36
|
description: Access to per Rails environment configuration stored in a YAML file
|
22
|
-
email:
|
37
|
+
email:
|
38
|
+
- contact@davidbarral.com
|
23
39
|
executables: []
|
24
|
-
|
25
40
|
extensions: []
|
26
|
-
|
27
41
|
extra_rdoc_files: []
|
28
|
-
|
29
|
-
|
30
|
-
-
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- Gemfile
|
45
|
+
- Gemfile.lock
|
31
46
|
- LICENSE
|
47
|
+
- README.rdoc
|
48
|
+
- Rakefile
|
32
49
|
- init.rb
|
33
50
|
- lib/sugarfree-config.rb
|
34
|
-
|
51
|
+
- lib/sugarfree-config/config.rb
|
52
|
+
- lib/sugarfree-config/exceptions.rb
|
53
|
+
- lib/sugarfree-config/version.rb
|
54
|
+
- specs/config_spec.rb
|
55
|
+
- specs/exceptions_spec.rb
|
56
|
+
- specs/spec_helper.rb
|
57
|
+
- specs/sugarfree_spec.rb
|
58
|
+
- sugarfree-config.gemspec
|
35
59
|
homepage: http://github.com/davidbarral/sugarfree-config
|
36
60
|
licenses: []
|
37
|
-
|
38
61
|
post_install_message:
|
39
62
|
rdoc_options: []
|
40
|
-
|
41
|
-
require_paths:
|
63
|
+
require_paths:
|
42
64
|
- lib
|
43
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
requirements:
|
52
|
-
- -
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
55
|
-
- 0
|
56
|
-
version: "0"
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
57
77
|
requirements: []
|
58
|
-
|
59
78
|
rubyforge_project:
|
60
|
-
rubygems_version: 1.
|
79
|
+
rubygems_version: 1.8.6
|
61
80
|
signing_key:
|
62
81
|
specification_version: 3
|
63
82
|
summary: Configuration handling the easy way
|
64
83
|
test_files: []
|
65
|
-
|