runcoderun-configatron 2.2.1.1

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 ADDED
@@ -0,0 +1,132 @@
1
+ =Configatron
2
+
3
+ Configatron makes configuring your applications and scripts incredibly easy. No longer is a there a need to use constants or global variables. Now you can use a simple and painless system to configure your life. And, because it's all Ruby, you can do any crazy thing you would like to!
4
+
5
+ ==Examples
6
+
7
+ ===Simple
8
+ configatron.email = 'me@example.com'
9
+ configatron.database_url = "postgres://localhost/mack_framework_rocks"
10
+
11
+ Now, anywhere in your code you can do the following:
12
+
13
+ configatron.email # => "me@example.com"
14
+ configatron.database_url # => "postgres://localhost/mack_framework_rocks"
15
+
16
+ Viola! Simple as can be.
17
+
18
+ Now you're saying, what if I want to have a 'default' set of options, but then override them later, based on other information? Simple again. Let's use our above example. We've configured our 'database_url' option to be "postgres://localhost/mack_framework_rocks". The problem with that is that is our production database url, not our development url. Fair enough, all you have to do is redeclare it:
19
+
20
+ configatron.database_url = "postgres://localhost/mack_framework_rocks_development"
21
+
22
+
23
+ becomes:
24
+
25
+ configatron.email # => "me@example.com"
26
+ configatron.database_url # => "postgres://localhost/mack_framework_rocks_development"
27
+
28
+ Notice how our other configuration parameters haven't changed? Cool, eh?
29
+
30
+ ===Hash/YAML
31
+ You can configure configatron from a hash as well:
32
+
33
+ configatron.configure_from_hash({:email => {:pop => {:address => 'pop.example.com', :port => 110}}, :smtp => {:address => 'smtp.example.com'}})
34
+
35
+ configatron.email.pop.address # => 'pop.example.com'
36
+ configatron.email.pop.port # => 110
37
+ # and so on...
38
+
39
+ Notice how they're all namespaced for your as well. The same holds true for YAML files:
40
+
41
+ configuration.configure_from_yaml('/path/to/file.yml')
42
+
43
+ When the 'reload' method is called on configatron then the YAML file will be re-read in case changes have been made.
44
+
45
+ ===Namespaces
46
+
47
+ The question that should be on your lips is what I need to have namespaced configuration parameters. It's easy! Configatron allows you to create namespaces.
48
+
49
+ configatron.website_url = "http://www.mackframework.com"
50
+ configatron.email.pop.address = "pop.example.com"
51
+ configatron.email.pop.port = 110
52
+ configatron.email.smtp.address = "smtp.example.com"
53
+ configatron.email.smtp.port = 25
54
+
55
+ becomes:
56
+
57
+ configatron.email.pop.address # => "pop.example.com"
58
+ configatron.email.smtp.address # => "smtp.example.com"
59
+ configatron.website_url # => "http://www.mackframework.com"
60
+
61
+ Configatron allows you to nest namespaces to your hearts content! Just keep going, it's that easy.
62
+
63
+ Of course you can update a single parameter n levels deep as well:
64
+
65
+ configatron.email.pop.address = "pop2.example.com"
66
+
67
+ configatron.email.pop.address # => "pop2.example.com"
68
+ configatron.email.smtp.address # => "smtp.example.com"
69
+
70
+ ===Misc.
71
+
72
+ Even if parameters haven't been set, you can still call them, and you'll get nil back:
73
+
74
+ configatron.i.dont.exist.nil? # => true
75
+ configatron.i.dont.exist # => nil
76
+
77
+ You can set 'default' values for parameters. If there is already a setting, it won't be replaced. This is useful if you've already done your 'configuration' and you call a library, that needs to have parameters set. The library can set it's defaults, without worrying that it might have overridden your custom settings.
78
+
79
+ configatron.set_default(:name, 'Mark Bates')
80
+ configatron.name # => 'Mark Bates'
81
+ configatron.set_default(:name, 'Me')
82
+ configatron.name # => 'Mark Bates'
83
+
84
+ Sometimes in testing, or other situations, you want to temporarily change some settings. You can do this with the <tt>temp</tt> method:
85
+
86
+ configatron.one = 1
87
+ configatron.letters.a = 'A'
88
+ configatron.letters.b = 'B'
89
+ configatron.temp do
90
+ configatron.letters.b = 'bb'
91
+ configatron.letters.c = 'c'
92
+ configatron.one # => 1
93
+ configatron.letters.a # => 'A'
94
+ configatron.letters.b # => 'bb'
95
+ configatron.letters.c # => 'c'
96
+ end
97
+ configatron.one # => 1
98
+ configatron.letters.a # => 'A'
99
+ configatron.letters.b # => 'B'
100
+ configatron.letters.c # => nil
101
+
102
+ You can also pass in an optional Hash to the <tt>temp</tt>:
103
+
104
+ configatron.one = 1
105
+ configatron.letters.a = 'A'
106
+ configatron.letters.b = 'B'
107
+ configatron.temp(:letters => {:b => 'bb', :c => 'c'}) do
108
+ configatron.one == 1
109
+ configatron.letters.a # => 'A'
110
+ configatron.letters.b # => 'bb'
111
+ configatron.letters.c # => 'c'
112
+ end
113
+ configatron.one == 1
114
+ configatron.letters.a # => 'A'
115
+ configatron.letters.b # => 'B'
116
+ configatron.letters.c # => nil
117
+
118
+ Enjoy!
119
+
120
+ ==Contact
121
+ Please mail bugs, suggestions and patches to <bugs@mackframework.com>.
122
+
123
+ On the web at: http://www.mackframework.com
124
+
125
+ ==License and Copyright
126
+ Copyright (C) 2008 Mark Bates, http://www.mackframework.com
127
+
128
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
129
+
130
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
131
+
132
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,54 @@
1
+ require 'singleton'
2
+
3
+ class Configatron
4
+ include Singleton
5
+
6
+ alias_method :send!, :send
7
+
8
+ def initialize # :nodoc:
9
+ @_namespace = [:default]
10
+ reset!
11
+ end
12
+
13
+ # Forwards the method call onto the 'namespaced' Configatron::Store
14
+ def method_missing(sym, *args)
15
+ @_store[@_namespace.last].send(sym, *args)
16
+ end
17
+
18
+ # Removes ALL configuration parameters
19
+ def reset!
20
+ @_store = {:default => Configatron::Store.new}
21
+ end
22
+
23
+ # Allows for the temporary overriding of parameters in a block.
24
+ # Takes an optional Hash of parameters that will be applied before
25
+ # the block gets called. At the end of the block, the temporary
26
+ # settings are deleted and the original settings are reinstated.
27
+ def temp(options = nil)
28
+ begin
29
+ temp_start(options)
30
+ yield
31
+ rescue Exception => e
32
+ raise e
33
+ ensure
34
+ temp_end
35
+ end
36
+ end
37
+
38
+ def temp_start(options = nil)
39
+ n_space = rand
40
+ @_store[n_space] = @_store[@_namespace.last].deep_clone
41
+ @_namespace << n_space
42
+ if options
43
+ self.method_missing(:configure_from_hash, options)
44
+ end
45
+ end
46
+
47
+ def temp_end
48
+ @_store.delete(@_namespace.pop)
49
+ end
50
+
51
+ undef :inspect # :nodoc:
52
+ undef :nil? # :nodoc:
53
+
54
+ end
@@ -0,0 +1,13 @@
1
+ class Configatron
2
+ class ProtectedParameter < StandardError
3
+ def intialize(name)
4
+ super("Can not modify protected parameter: '#{name}'")
5
+ end
6
+ end
7
+
8
+ class LockedNamespace < StandardError
9
+ def initialize(name)
10
+ super("Cannot add new parameters to locked namespace: #{name.inspect}")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ module Kernel
2
+
3
+ # Provides access to the Configatron storage system.
4
+ def configatron
5
+ Configatron.instance
6
+ end
7
+
8
+ end
@@ -0,0 +1,255 @@
1
+ class Configatron
2
+ class Store
3
+ alias_method :send!, :send
4
+
5
+ # Takes an optional Hash of parameters
6
+ def initialize(options = {}, name = nil, parent = nil)
7
+ @_name = name
8
+ @_parent = parent
9
+ @_store = {}
10
+ configure_from_hash(options)
11
+ @_protected = []
12
+ end
13
+
14
+ # Returns a Hash representing the configurations
15
+ def to_hash
16
+ @_store
17
+ end
18
+
19
+ def inspect
20
+ path = [@_name]
21
+ parent = @_parent
22
+ until parent.nil?
23
+ path << parent.instance_variable_get('@_name')
24
+ parent = parent.instance_variable_get('@_parent')
25
+ end
26
+ path << 'configatron'
27
+ path.compact!
28
+ path.reverse!
29
+ f_out = []
30
+ @_store.each do |k, v|
31
+ if v.is_a?(Configatron::Store)
32
+ v.inspect.each_line do |line|
33
+ if line.match(/\n/)
34
+ line.each_line do |l|
35
+ l.strip!
36
+ f_out << l
37
+ end
38
+ else
39
+ line.strip!
40
+ f_out << line
41
+ end
42
+ end
43
+ else
44
+ f_out << "#{path.join('.')}.#{k} = #{v.inspect}"
45
+ end
46
+ end
47
+ f_out.compact.sort.join("\n")
48
+ end
49
+
50
+ # Allows for the configuration of the system via a Hash
51
+ def configure_from_hash(options)
52
+ parse_options(options)
53
+ end
54
+
55
+ # Allows for the configuration of the system from a YAML file.
56
+ # Takes the path to the YAML file. Also takes an optional parameter,
57
+ # <tt>:hash</tt>, that indicates a specific hash that should be
58
+ # loaded from the file.
59
+ def configure_from_yaml(path, opts = {})
60
+ begin
61
+ yml = YAML.load(ERB.new(File.read(path)).result)
62
+ yml = yml[opts[:hash]] unless opts[:hash].nil?
63
+ configure_from_hash(yml)
64
+ rescue Errno::ENOENT => e
65
+ puts e.message
66
+ end
67
+ end
68
+
69
+ # Returns true if there are no configuration parameters
70
+ def nil?
71
+ return @_store.empty?
72
+ end
73
+
74
+ # Retrieves a certain parameter and if that parameter
75
+ # doesn't exist it will return the default_value specified.
76
+ def retrieve(name, default_value = nil)
77
+ @_store[name.to_sym] || default_value
78
+ end
79
+
80
+ # Removes a parameter. In the case of a nested parameter
81
+ # it will remove all below it.
82
+ def remove(name)
83
+ @_store.delete(name.to_sym)
84
+ end
85
+
86
+ # Sets a 'default' value. If there is already a value specified
87
+ # it won't set the value.
88
+ def set_default(name, default_value)
89
+ unless @_store[name.to_sym]
90
+ @_store[name.to_sym] = parse_options(default_value)
91
+ end
92
+ end
93
+
94
+ def method_missing(sym, *args) # :nodoc:
95
+ if sym.to_s.match(/(.+)=$/)
96
+ name = sym.to_s.gsub("=", '').to_sym
97
+ raise Configatron::ProtectedParameter.new(name) if @_protected.include?(name) || methods_include?(name)
98
+ raise Configatron::LockedNamespace.new(@_name) if @_locked && !@_store.has_key?(name)
99
+ @_store[name] = parse_options(*args)
100
+ elsif @_store.has_key?(sym)
101
+ return @_store[sym]
102
+ else
103
+ store = Configatron::Store.new({}, sym, self)
104
+ @_store[sym] = store
105
+ return store
106
+ end
107
+ end
108
+
109
+ def ==(other) # :nodoc:
110
+ self.to_hash == other
111
+ end
112
+
113
+ # Prevents a parameter from being reassigned. If called on a 'namespace' then
114
+ # all parameters below it will be protected as well.
115
+ def protect(name)
116
+ @_protected << name.to_sym
117
+ end
118
+
119
+ # Prevents all parameters from being reassigned.
120
+ def protect_all!
121
+ @_protected.clear
122
+ @_store.keys.each do |k|
123
+ val = self.send(k)
124
+ val.protect_all! if val.class == Configatron::Store
125
+ @_protected << k
126
+ end
127
+ end
128
+
129
+ # Removes the protection of a parameter.
130
+ def unprotect(name)
131
+ @_protected.reject! { |e| e == name.to_sym }
132
+ end
133
+
134
+ def unprotect_all!
135
+ @_protected.clear
136
+ @_store.keys.each do |k|
137
+ val = self.send(k)
138
+ val.unprotect_all! if val.class == Configatron::Store
139
+ end
140
+ end
141
+
142
+ # Prevents a namespace from having new parameters set. The lock is applied
143
+ # recursively to any namespaces below it.
144
+ def lock(name)
145
+ namespace = @_store[name.to_sym]
146
+ raise ArgumentError, "Namespace #{name.inspect} does not exist" if namespace.nil?
147
+ namespace.lock!
148
+ end
149
+
150
+ def unlock(name)
151
+ namespace = @_store[name.to_sym]
152
+ raise ArgumentError, "Namespace #{name.inspect} does not exist" if namespace.nil?
153
+ namespace.unlock!
154
+ end
155
+
156
+ # = DeepClone
157
+ #
158
+ # == Version
159
+ # 1.2006.05.23 (change of the first number means Big Change)
160
+ #
161
+ # == Description
162
+ # Adds deep_clone method to an object which produces deep copy of it. It means
163
+ # if you clone a Hash, every nested items and their nested items will be cloned.
164
+ # Moreover deep_clone checks if the object is already cloned to prevent endless recursion.
165
+ #
166
+ # == Usage
167
+ #
168
+ # (see examples directory under the ruby gems root directory)
169
+ #
170
+ # require 'rubygems'
171
+ # require 'deep_clone'
172
+ #
173
+ # include DeepClone
174
+ #
175
+ # obj = []
176
+ # a = [ true, false, obj ]
177
+ # b = a.deep_clone
178
+ # obj.push( 'foo' )
179
+ # p obj # >> [ 'foo' ]
180
+ # p b[2] # >> []
181
+ #
182
+ # == Source
183
+ # http://simplypowerful.1984.cz/goodlibs/1.2006.05.23
184
+ #
185
+ # == Author
186
+ # jan molic (/mig/at_sign/1984/dot/cz/)
187
+ #
188
+ # == Licence
189
+ # You can redistribute it and/or modify it under the same terms of Ruby's license;
190
+ # either the dual license version in 2003, or any later version.
191
+ #
192
+ def deep_clone( obj=self, cloned={} )
193
+ if cloned.has_key?( obj.object_id )
194
+ return cloned[obj.object_id]
195
+ else
196
+ begin
197
+ cl = obj.clone
198
+ rescue Exception
199
+ # unclonnable (TrueClass, Fixnum, ...)
200
+ cloned[obj.object_id] = obj
201
+ return obj
202
+ else
203
+ cloned[obj.object_id] = cl
204
+ cloned[cl.object_id] = cl
205
+ if cl.is_a?( Hash )
206
+ cl.clone.each { |k,v|
207
+ cl[k] = deep_clone( v, cloned )
208
+ }
209
+ elsif cl.is_a?( Array )
210
+ cl.collect! { |v|
211
+ deep_clone( v, cloned )
212
+ }
213
+ end
214
+ cl.instance_variables.each do |var|
215
+ v = cl.instance_eval( var.to_s )
216
+ v_cl = deep_clone( v, cloned )
217
+ cl.instance_eval( "#{var} = v_cl" )
218
+ end
219
+ return cl
220
+ end
221
+ end
222
+ end
223
+
224
+ protected
225
+ def lock!
226
+ @_locked = true
227
+ @_store.values.each { |store| store.lock! if store.is_a?(Configatron::Store) }
228
+ end
229
+
230
+ def unlock!
231
+ @_locked = false
232
+ @_store.values.each { |store| store.unlock! if store.is_a?(Configatron::Store) }
233
+ end
234
+
235
+ private
236
+ def methods_include?(name)
237
+ self.methods.include?(RUBY_VERSION > '1.9.0' ? name.to_sym : name.to_s)
238
+ end
239
+
240
+ def parse_options(options)
241
+ if options.is_a?(Hash)
242
+ options.each do |k,v|
243
+ if v.is_a?(Hash)
244
+ self.method_missing(k.to_sym).configure_from_hash(v)
245
+ else
246
+ self.method_missing("#{k.to_sym}=", v)
247
+ end
248
+ end
249
+ else
250
+ return options
251
+ end
252
+ end
253
+
254
+ end
255
+ end
@@ -0,0 +1,7 @@
1
+ base = File.join(File.dirname(__FILE__), 'configatron')
2
+ require 'yaml'
3
+ require 'erb'
4
+ require File.join(base, 'kernel')
5
+ require File.join(base, 'configatron')
6
+ require File.join(base, 'store')
7
+ require File.join(base, 'errors')
@@ -0,0 +1,449 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe "configatron" do
4
+
5
+ before(:each) do
6
+ configatron.reset!
7
+ end
8
+
9
+ describe 'protect' do
10
+
11
+ it 'should protect a parameter and prevent it from being set' do
12
+ configatron.one = 1
13
+ configatron.protect(:one)
14
+ lambda{configatron.one = 'one'}.should raise_error(Configatron::ProtectedParameter)
15
+ configatron.one.should == 1
16
+ end
17
+
18
+ it 'should protect basic methods' do
19
+ lambda{configatron.object_id = 123456}.should raise_error(Configatron::ProtectedParameter)
20
+ lambda{configatron.foo.object_id = 123456}.should raise_error(Configatron::ProtectedParameter)
21
+ end
22
+
23
+ it 'should work with nested parameters' do
24
+ configatron.one = 1
25
+ configatron.letters.a = 'A'
26
+ configatron.letters.b = 'B'
27
+ configatron.letters.protect(:a)
28
+ lambda{configatron.letters.a = 'a'}.should raise_error(Configatron::ProtectedParameter)
29
+ configatron.letters.a.should == 'A'
30
+ configatron.protect(:letters)
31
+ lambda{configatron.letters.a = 'a'}.should raise_error(Configatron::ProtectedParameter)
32
+ lambda{configatron.letters = 'letter'}.should raise_error(Configatron::ProtectedParameter)
33
+ end
34
+
35
+ it 'should work with configure_from_hash' do
36
+ configatron.one = 1
37
+ configatron.letters.a = 'A'
38
+ configatron.letters.b = 'B'
39
+ configatron.letters.protect(:a)
40
+ lambda{configatron.configure_from_hash(:letters => {:a => 'a'})}.should raise_error(Configatron::ProtectedParameter)
41
+ configatron.letters.a.should == 'A'
42
+ configatron.protect(:letters)
43
+ lambda{configatron.letters.configure_from_hash(:a => 'a')}.should raise_error(Configatron::ProtectedParameter)
44
+ lambda{configatron.configure_from_hash(:letters => 'letters')}.should raise_error(Configatron::ProtectedParameter)
45
+ end
46
+
47
+ it "should be able to protect all parameters at once" do
48
+ configatron.one = 1
49
+ configatron.letters.a = 'A'
50
+ configatron.letters.b = 'B'
51
+ configatron.protect_all!
52
+ [:a,:b].each do |l|
53
+ lambda{configatron.configure_from_hash(:letters => {l => l.to_s})}.should raise_error(Configatron::ProtectedParameter)
54
+ configatron.letters.send(l).should == l.to_s.upcase
55
+ end
56
+ lambda{configatron.letters.configure_from_hash(:a => 'a')}.should raise_error(Configatron::ProtectedParameter)
57
+ lambda{configatron.configure_from_hash(:letters => 'letters')}.should raise_error(Configatron::ProtectedParameter)
58
+ end
59
+
60
+ it "should be able to unprotect a parameter" do
61
+ configatron.one = 1
62
+ configatron.protect(:one)
63
+ configatron.unprotect(:one)
64
+ lambda{configatron.one = 2}.should_not raise_error
65
+ end
66
+
67
+ it "should be able to unprotect all parameters at once" do
68
+ configatron.one = 1
69
+ configatron.letters.a = 'A'
70
+ configatron.letters.b = 'B'
71
+ configatron.protect_all!
72
+ configatron.unprotect_all!
73
+ lambda{configatron.one = 2}.should_not raise_error
74
+ lambda{configatron.letters.configure_from_hash(:a => 'a')}.should_not raise_error
75
+ end
76
+
77
+ end
78
+
79
+ describe 'lock' do
80
+ before :each do
81
+ configatron.letters.a = 'A'
82
+ configatron.letters.b = 'B'
83
+ configatron.letters.greek.alpha = 'alpha'
84
+ configatron.lock(:letters)
85
+ end
86
+
87
+ it 'should allow setting of existing parameters in locked parameter' do
88
+ lambda { configatron.letters.a = 'a' }.should_not raise_error
89
+ end
90
+
91
+ it 'should not allow setting of a parameter that is not already set' do
92
+ lambda { configatron.letters.c = 'C' }.should raise_error(Configatron::LockedNamespace)
93
+ end
94
+
95
+ it 'should allow setting of existing parameters in child of locked parameter' do
96
+ lambda { configatron.letters.greek.alpha = 'a' }.should_not raise_error
97
+ end
98
+
99
+ it 'should not allow setting of new parameters in child of locked parameter' do
100
+ lambda { configatron.letters.greek.beta = 'beta' }.should raise_error(Configatron::LockedNamespace)
101
+ end
102
+
103
+ it 'should not affect parameters below the locked namespace' do
104
+ lambda { configatron.one = 1 }.should_not raise_error
105
+ end
106
+
107
+ it 'should raise an ArgumentError if unknown namespace is locked' do
108
+ lambda { configatron.lock(:numbers).should raise_error(ArgumentError) }
109
+ end
110
+
111
+ describe 'then unlock' do
112
+ before :each do
113
+ configatron.unlock(:letters)
114
+ end
115
+
116
+ it 'should allow setting of new parameter in unlocked namespace' do
117
+ lambda { configatron.letters.d = 'd' }.should_not raise_error
118
+ end
119
+
120
+ it 'should allow setting of new parameter in unlocked namespace\'s child' do
121
+ lambda { configatron.letters.greek.zeta = 'z' }.should_not raise_error
122
+ end
123
+
124
+ it 'should raise an ArgumentError if unknown namespace is unlocked' do
125
+ lambda { configatron.unlock(:numbers).should raise_error(ArgumentError) }
126
+ end
127
+ end
128
+ end
129
+
130
+ describe 'temp' do
131
+
132
+ it 'should revert back to the original parameters when the block ends' do
133
+ configatron.one = 1
134
+ configatron.letters.a = 'A'
135
+ configatron.letters.b = 'B'
136
+ configatron.temp do
137
+ configatron.letters.b = 'bb'
138
+ configatron.letters.c = 'c'
139
+ configatron.one.should == 1
140
+ configatron.letters.a.should == 'A'
141
+ configatron.letters.b.should == 'bb'
142
+ configatron.letters.c.should == 'c'
143
+ end
144
+ configatron.one.should == 1
145
+ configatron.letters.a.should == 'A'
146
+ configatron.letters.b.should == 'B'
147
+ configatron.letters.c.should be_nil
148
+ end
149
+
150
+ it 'should take an optional hash of parameters' do
151
+ configatron.one = 1
152
+ configatron.letters.a = 'A'
153
+ configatron.letters.b = 'B'
154
+ configatron.temp(:letters => {:b => 'bb', :c => 'c'}) do
155
+ configatron.one.should == 1
156
+ configatron.letters.a.should == 'A'
157
+ configatron.letters.b.should == 'bb'
158
+ configatron.letters.c.should == 'c'
159
+ end
160
+ configatron.one.should == 1
161
+ configatron.letters.a.should == 'A'
162
+ configatron.letters.b.should == 'B'
163
+ configatron.letters.c.should be_nil
164
+ end
165
+
166
+ it 'should work the same as temp_start/temp_end' do
167
+ configatron.one = 1
168
+ configatron.temp_start
169
+ configatron.one = 'ONE'
170
+ configatron.one.should == 'ONE'
171
+ configatron.temp_end
172
+ configatron.one.should == 1
173
+ end
174
+
175
+ it 'should be able to nest' do
176
+ configatron.one = 1
177
+ configatron.letters.a = 'A'
178
+ configatron.letters.b = 'B'
179
+ configatron.temp do
180
+ configatron.letters.b = 'bb'
181
+ configatron.letters.c = 'c'
182
+ configatron.one.should == 1
183
+ configatron.letters.a.should == 'A'
184
+ configatron.letters.b.should == 'bb'
185
+ configatron.letters.c.should == 'c'
186
+ configatron.temp do
187
+ configatron.letters.b = 'bbb'
188
+ configatron.one.should == 1
189
+ configatron.letters.a.should == 'A'
190
+ configatron.letters.b.should == 'bbb'
191
+ configatron.letters.c.should == 'c'
192
+ end
193
+ end
194
+ configatron.one.should == 1
195
+ configatron.letters.a.should == 'A'
196
+ configatron.letters.b.should == 'B'
197
+ configatron.letters.c.should be_nil
198
+ end
199
+
200
+ end
201
+
202
+ describe 'configure_from_hash' do
203
+
204
+ it 'should configure itself from a hash' do
205
+ configatron.foo.should be_nil
206
+ configatron.configure_from_hash(:foo => :bar)
207
+ configatron.foo.should == :bar
208
+ end
209
+
210
+ it 'should handled deeply nested params' do
211
+ configatron.friends.rachel.should be_nil
212
+ configatron.configure_from_hash(:friends => {:rachel => 'Rachel Green'})
213
+ configatron.friends.rachel.should == 'Rachel Green'
214
+ end
215
+
216
+ it 'should not remove previously defined params' do
217
+ configatron.friends.rachel = 'Rachel Green'
218
+ configatron.friends.ross = 'Ross Gellar'
219
+ configatron.friends.monica = 'Monica Gellar'
220
+ configatron.configure_from_hash(:friends => {:rachel => 'R. Green', :monica => 'Monica Bing'})
221
+ configatron.friends.ross.should == 'Ross Gellar'
222
+ configatron.friends.rachel.should == 'R. Green'
223
+ configatron.friends.monica.should == 'Monica Bing'
224
+ end
225
+
226
+ end
227
+
228
+ describe 'configure_from_yaml' do
229
+
230
+ it 'should configure itself from a yaml file' do
231
+ configatron.futurama.should be_nil
232
+ configatron.configure_from_yaml(File.join(File.dirname(__FILE__), 'futurama.yml'))
233
+ configatron.futurama.robots.bender.should == 'Bender The Robot'
234
+ end
235
+
236
+ it 'should not remove previously defined params' do
237
+ configatron.futurama.mutants.leela = 'Leela'
238
+ configatron.configure_from_yaml(File.join(File.dirname(__FILE__), 'futurama.yml'))
239
+ configatron.futurama.robots.bender.should == 'Bender The Robot'
240
+ configatron.futurama.mutants.leela = 'Leela'
241
+ end
242
+
243
+ it "should fail silently if the file doesn't exist" do
244
+ lambda{configatron.configure_from_yaml('i_dont_exist.yml')}.should_not raise_error
245
+ end
246
+
247
+ it "should be able to load a specific hash from the file" do
248
+ configatron.others.should be_nil
249
+ configatron.survivors.should be_nil
250
+ configatron.configure_from_yaml(File.join(File.dirname(__FILE__), 'lost.yml'), :hash => "survivors")
251
+ configatron.others.should be_nil
252
+ configatron.survivors.should be_nil
253
+ configatron.on_island.jack.should == 'Jack Shepherd'
254
+ end
255
+
256
+ class WireHelper
257
+ def self.best_show_on_tv?
258
+ true
259
+ end
260
+ end
261
+
262
+ it "should be able to use ERB in yaml" do
263
+ AVON = "Avon Barksdale"
264
+ configatron.simpsons.should be_nil
265
+ configatron.configure_from_yaml(File.join(File.dirname(__FILE__), 'the_wire.yml'))
266
+ configatron.police.jimmy.should == "Jimmy McNulty"
267
+ configatron.best_show_on_tv.should == true
268
+ configatron.dealers.avon.should == "Avon Barksdale"
269
+ end
270
+
271
+ end
272
+
273
+ it 'should return a parameter' do
274
+ configatron.foo = :bar
275
+ configatron.foo.should == :bar
276
+ end
277
+
278
+ it 'should return a nested parameter' do
279
+ configatron.children.dylan = 'Dylan Bates'
280
+ configatron.children.dylan.should == 'Dylan Bates'
281
+ end
282
+
283
+ it 'should set a nested parameter and not remove previously defined params' do
284
+ configatron.friends.rachel = 'Rachel Green'
285
+ configatron.friends.rachel.should == 'Rachel Green'
286
+ configatron.friends.ross = 'Ross Gellar'
287
+ configatron.friends.ross.should == 'Ross Gellar'
288
+ configatron.friends.monica = 'Monica Gellar'
289
+ configatron.friends.monica.should == 'Monica Gellar'
290
+ configatron.friends.rachel = 'R. Green'
291
+ configatron.friends.monica = 'Monica Bing'
292
+ configatron.friends.rachel.should == 'R. Green'
293
+ configatron.friends.ross.should == 'Ross Gellar'
294
+ configatron.friends.monica.should == 'Monica Bing'
295
+ end
296
+
297
+ it 'should return the Configatron instance' do
298
+ configatron.should be_is_a(Configatron)
299
+ end
300
+
301
+ describe 'to_hash' do
302
+
303
+ it 'should return a hash of all the params' do
304
+ configatron.one = 1
305
+ configatron.letters.a = 'A'
306
+ configatron.letters.b = 'B'
307
+ configatron.to_hash.should == {:one => 1, :letters => {:a => 'A', :b => 'B'}}
308
+ end
309
+
310
+ end
311
+
312
+ describe 'inspect' do
313
+
314
+ it 'should call return the inspect method of the to_hash method' do
315
+ configatron.one = 1
316
+ configatron.letters.a = 'A'
317
+ configatron.letters.b = 'B'
318
+ configatron.numbers.small.one = 1
319
+ configatron.numbers.small.others = [2,3]
320
+ configatron.numbers.big.one.hundred = '100'
321
+
322
+ configatron.inspect.should == %{
323
+ configatron.letters.a = "A"
324
+ configatron.letters.b = "B"
325
+ configatron.numbers.big.one.hundred = "100"
326
+ configatron.numbers.small.one = 1
327
+ configatron.numbers.small.others = [2, 3]
328
+ configatron.one = 1
329
+ }.strip
330
+
331
+ end
332
+
333
+ end
334
+
335
+ describe 'nil?' do
336
+
337
+ it 'should return true if there are no parameters' do
338
+ configatron.should be_nil
339
+ configatron.friends.should be_nil
340
+ end
341
+
342
+ it 'should return true if there are no parameters on a nested parameter' do
343
+ configatron.friends.monica.should be_nil
344
+ end
345
+
346
+ end
347
+
348
+ describe 'retrieve' do
349
+
350
+ it 'should retrieve a parameter' do
351
+ configatron.office = 'Michael'
352
+ configatron.retrieve(:office).should == 'Michael'
353
+ end
354
+
355
+ it 'should return the optional second parameter if the config setting is nil' do
356
+ configatron.retrieve(:office, 'Stanley').should == 'Stanley'
357
+ end
358
+
359
+ it 'should work with a symbol or a string' do
360
+ configatron.office = 'Michael'
361
+ configatron.retrieve(:office).should == 'Michael'
362
+ configatron.retrieve('office').should == 'Michael'
363
+ end
364
+
365
+ it 'should work on nested parameters' do
366
+ configatron.the.office = 'Michael'
367
+ configatron.the.retrieve(:office).should == 'Michael'
368
+ configatron.the.retrieve('office').should == 'Michael'
369
+ end
370
+
371
+ end
372
+
373
+ describe 'remove' do
374
+
375
+ it 'should remove a parameter' do
376
+ configatron.movies = 'Pulp Fiction'
377
+ configatron.movies.should == 'Pulp Fiction'
378
+ configatron.remove(:movies)
379
+ configatron.movies.should be_nil
380
+ end
381
+
382
+ it 'should remove a nested parameter' do
383
+ configatron.the.movies = 'Pulp Fiction'
384
+ configatron.the.movies.should == 'Pulp Fiction'
385
+ configatron.the.remove(:movies)
386
+ configatron.the.movies.should be_nil
387
+ end
388
+
389
+ it 'should work with a symbol or a string' do
390
+ configatron.the.movies = 'Pulp Fiction'
391
+ configatron.the.office = 'Michael'
392
+ configatron.the.remove(:movies)
393
+ configatron.the.movies.should be_nil
394
+ configatron.the.remove('office')
395
+ configatron.the.office.should be_nil
396
+ end
397
+
398
+ it 'should remove all sub-parameters' do
399
+ configatron.the.movies = 'Pulp Fiction'
400
+ configatron.the.office = 'Michael'
401
+ configatron.remove(:the)
402
+ configatron.the.should be_nil
403
+ configatron.the.movies.should be_nil
404
+ end
405
+
406
+ end
407
+
408
+ describe 'set_default' do
409
+
410
+ it 'should set a default parameter value' do
411
+ configatron.set_default(:movies, 'Pulp Fiction')
412
+ configatron.movies.should == 'Pulp Fiction'
413
+ end
414
+
415
+ it 'should set a default parameter value for a nested parameter' do
416
+ configatron.the.set_default(:movies, 'Pulp Fiction')
417
+ configatron.the.movies.should == 'Pulp Fiction'
418
+ end
419
+
420
+ it 'should not set the parameter if it is already set' do
421
+ configatron.movies = 'Transformers'
422
+ configatron.set_default(:movies, 'Pulp Fiction')
423
+ configatron.movies.should == 'Transformers'
424
+ end
425
+
426
+ it 'should not set the nested parameter if it is already set' do
427
+ configatron.the.movies = 'Transformers'
428
+ configatron.the.set_default(:movies, 'Pulp Fiction')
429
+ configatron.the.movies.should == 'Transformers'
430
+ end
431
+
432
+ end
433
+
434
+ describe 'reset!' do
435
+
436
+ it 'should clear out all parameter' do
437
+ configatron.one = 1
438
+ configatron.letters.a = 'A'
439
+ configatron.letters.b = 'B'
440
+ configatron.one.should == 1
441
+ configatron.letters.a.should == 'A'
442
+ configatron.reset!
443
+ configatron.one.should be_nil
444
+ configatron.letters.a.should be_nil
445
+ end
446
+
447
+ end
448
+
449
+ end
@@ -0,0 +1,6 @@
1
+ futurama:
2
+ robots:
3
+ bender: Bender The Robot
4
+ humans:
5
+ fry: Philip J. Fry
6
+ amy: Amy Wong
data/spec/lib/lost.yml ADDED
@@ -0,0 +1,14 @@
1
+ others:
2
+ on_island:
3
+ ben: Benjamin Linus
4
+ richard: Richard Alpert
5
+ deceased:
6
+ goodwin: Goodwin Stanhope
7
+ mikhail: Mikhail Bakunin
8
+ survivors:
9
+ on_island:
10
+ jack: Jack Shepherd
11
+ locke: John Locke
12
+ deceased:
13
+ charlie: Charlie Pace
14
+ michael: Michael Dawson
@@ -0,0 +1,5 @@
1
+ best_show_on_tv: <%= WireHelper.best_show_on_tv? %>
2
+ police:
3
+ jimmy: Jimmy McNulty
4
+ dealers:
5
+ avon: <%= AVON %>
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'configatron')
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: runcoderun-configatron
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.2.1.1
5
+ platform: ruby
6
+ authors:
7
+ - markbates
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-14 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: "Configatron was developed by: markbates"
17
+ email: mark@mackframework.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - lib/configatron/configatron.rb
26
+ - lib/configatron/errors.rb
27
+ - lib/configatron/kernel.rb
28
+ - lib/configatron/store.rb
29
+ - lib/configatron.rb
30
+ - README
31
+ - spec/lib
32
+ - spec/lib/configatron_spec.rb
33
+ - spec/lib/futurama.yml
34
+ - spec/lib/lost.yml
35
+ - spec/lib/the_wire.yml
36
+ - spec/spec.opts
37
+ - spec/spec_helper.rb
38
+ has_rdoc: true
39
+ homepage: http://www.mackframework.com
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project: magrathea
61
+ rubygems_version: 1.2.0
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: A powerful Ruby configuration system.
65
+ test_files:
66
+ - spec/lib
67
+ - spec/lib/configatron_spec.rb
68
+ - spec/lib/futurama.yml
69
+ - spec/lib/lost.yml
70
+ - spec/lib/the_wire.yml
71
+ - spec/spec.opts
72
+ - spec/spec_helper.rb