markbates-configatron 2.3.2.20090731133933

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009 Mark Bates
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,143 @@
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
+ ==Installation
6
+
7
+ Installation of Configatron is easy, as it is just a RubyGem:
8
+
9
+ $ sudo gem install configatron
10
+
11
+ If you'd like to live on the bleedin' edge you can install the development version from GitHub:
12
+
13
+ $ sudo gem install markbates-configatron --source=http://gems.github.com
14
+
15
+ Once installed you just need to require it:
16
+
17
+ require 'configatron'
18
+
19
+ ==Examples
20
+
21
+ ===Simple
22
+
23
+ configatron.email = 'me@example.com'
24
+ configatron.database_url = "postgres://localhost/mack_framework_rocks"
25
+
26
+ Now, anywhere in your code you can do the following:
27
+
28
+ configatron.email # => "me@example.com"
29
+ configatron.database_url # => "postgres://localhost/mack_framework_rocks"
30
+
31
+ Viola! Simple as can be.
32
+
33
+ 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 <tt>database_url</tt> option to be <tt>postgres://localhost/mack_framework_rocks</tt>. 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:
34
+
35
+ configatron.database_url = "postgres://localhost/mack_framework_rocks_development"
36
+
37
+ becomes:
38
+
39
+ configatron.email # => "me@example.com"
40
+ configatron.database_url # => "postgres://localhost/mack_framework_rocks_development"
41
+
42
+ Notice how our other configuration parameters haven't changed? Cool, eh?
43
+
44
+ ===Hash/YAML
45
+
46
+ You can configure configatron from a hash as well:
47
+
48
+ configatron.configure_from_hash({:email => {:pop => {:address => 'pop.example.com', :port => 110}}, :smtp => {:address => 'smtp.example.com'}})
49
+
50
+ configatron.email.pop.address # => 'pop.example.com'
51
+ configatron.email.pop.port # => 110
52
+ # and so on...
53
+
54
+ Notice how they're all namespaced for your as well. The same holds true for YAML files:
55
+
56
+ configuration.configure_from_yaml('/path/to/file.yml')
57
+
58
+ ===Namespaces
59
+
60
+ 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.
61
+
62
+ configatron.website_url = "http://www.mackframework.com"
63
+ configatron.email.pop.address = "pop.example.com"
64
+ configatron.email.pop.port = 110
65
+ configatron.email.smtp.address = "smtp.example.com"
66
+ configatron.email.smtp.port = 25
67
+
68
+ becomes:
69
+
70
+ configatron.email.pop.address # => "pop.example.com"
71
+ configatron.email.smtp.address # => "smtp.example.com"
72
+ configatron.website_url # => "http://www.mackframework.com"
73
+
74
+ Configatron allows you to nest namespaces to your hearts content! Just keep going, it's that easy.
75
+
76
+ Of course you can update a single parameter n levels deep as well:
77
+
78
+ configatron.email.pop.address = "pop2.example.com"
79
+
80
+ configatron.email.pop.address # => "pop2.example.com"
81
+ configatron.email.smtp.address # => "smtp.example.com"
82
+
83
+ ===Misc.
84
+
85
+ Even if parameters haven't been set, you can still call them, but you'll get a <tt>Configatron::Store</tt> object back. The Configatron::Store class, however, will respond true to <tt>.nil?</tt> if there are no parameters configured on it.
86
+
87
+ configatron.i.dont.exist.nil? # => true
88
+ configatron.i.dont.exist # => Configatron::Store
89
+
90
+ If you want to get back an actual <tt>nil</tt> then you can use the <tt>retrieve</tt> method:
91
+
92
+ configatron.i.do.exist = [:some, :array]
93
+ configatron.i.dont.retrieve(:exist, nil) # => nil
94
+ configatron.i.do.retrieve(:exist, :foo) # => [:some, :array]
95
+
96
+ 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 its defaults, without worrying that it might have overridden your custom settings.
97
+
98
+ configatron.set_default(:name, 'Mark Bates')
99
+ configatron.name # => 'Mark Bates'
100
+ configatron.set_default(:name, 'Me')
101
+ configatron.name # => 'Mark Bates'
102
+
103
+ Sometimes in testing, or other situations, you want to temporarily change some settings. You can do this with the <tt>temp</tt> method:
104
+
105
+ configatron.one = 1
106
+ configatron.letters.a = 'A'
107
+ configatron.letters.b = 'B'
108
+ configatron.temp do
109
+ configatron.letters.b = 'bb'
110
+ configatron.letters.c = 'c'
111
+ configatron.one # => 1
112
+ configatron.letters.a # => 'A'
113
+ configatron.letters.b # => 'bb'
114
+ configatron.letters.c # => 'c'
115
+ end
116
+ configatron.one # => 1
117
+ configatron.letters.a # => 'A'
118
+ configatron.letters.b # => 'B'
119
+ configatron.letters.c # => nil
120
+
121
+ You can also pass in an optional Hash to the <tt>temp</tt>:
122
+
123
+ configatron.one = 1
124
+ configatron.letters.a = 'A'
125
+ configatron.letters.b = 'B'
126
+ configatron.temp(:letters => {:b => 'bb', :c => 'c'}) do
127
+ configatron.one == 1
128
+ configatron.letters.a # => 'A'
129
+ configatron.letters.b # => 'bb'
130
+ configatron.letters.c # => 'c'
131
+ end
132
+ configatron.one == 1
133
+ configatron.letters.a # => 'A'
134
+ configatron.letters.b # => 'B'
135
+ configatron.letters.c # => nil
136
+
137
+ Enjoy!
138
+
139
+ ==Contact
140
+
141
+ Please mail bugs, suggestions and patches to "development@metabates.com":mailto:development@metabates.com
142
+
143
+ On the web at: "http://www.metabates.com":http://www.metabates.com
@@ -0,0 +1,9 @@
1
+ base = File.join(File.dirname(__FILE__), 'configatron')
2
+ require 'yamler'
3
+ require File.join(base, 'configatron')
4
+ require File.join(base, 'store')
5
+ require File.join(base, 'errors')
6
+ require File.join(base, 'core_ext', 'kernel')
7
+ require File.join(base, 'core_ext', 'object')
8
+ require File.join(base, 'core_ext', 'string')
9
+ require File.join(base, 'core_ext', 'class')
@@ -0,0 +1,55 @@
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
+ undef :test # :nodoc:
54
+
55
+ end
@@ -0,0 +1,25 @@
1
+ class Class
2
+
3
+ # Returns access to configuration parameters named after the class.
4
+ #
5
+ # Examples:
6
+ # configatron.foo.bar = :bar
7
+ # configatron.a.b.c.d = 'D'
8
+ #
9
+ # class Foo
10
+ # end
11
+ #
12
+ # module A
13
+ # module B
14
+ # class C
15
+ # end
16
+ # end
17
+ # end
18
+ #
19
+ # Foo.to_configatron.bar # => :bar
20
+ # A::B::C.to_configatron.d # => 'D'
21
+ def to_configatron(*args)
22
+ self.name.to_configatron(*args)
23
+ end
24
+
25
+ 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,9 @@
1
+ class Object # :nodoc:
2
+
3
+ def send_with_chain(methods, *args) # :nodoc:
4
+ obj = self
5
+ [methods].flatten.each {|m| obj = obj.send(m, *args)}
6
+ obj
7
+ end
8
+
9
+ end
@@ -0,0 +1,90 @@
1
+ class String # :nodoc:
2
+
3
+ def to_configatron(*args)
4
+ name_spaces = (args + self.split("::")).flatten
5
+ name_spaces.collect!{|s| s.to_s.methodize}
6
+ configatron.send_with_chain(name_spaces)
7
+ end
8
+
9
+ def underscore # :nodoc:
10
+ self.to_s.gsub(/::/, '/').
11
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
12
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
13
+ tr("-", "_").
14
+ downcase
15
+ end
16
+
17
+ def methodize # :nodoc:
18
+ x = self
19
+
20
+ # if we get down to a nil or an empty string raise an exception!
21
+ raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
22
+
23
+ # get rid of the big stuff in the front/back
24
+ x.strip!
25
+
26
+ # if we get down to a nil or an empty string raise an exception!
27
+ raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
28
+
29
+ x = x.underscore
30
+
31
+ # get rid of spaces and make the _
32
+ x.gsub!(' ', '_')
33
+ # get rid of everything that isn't 'safe' a-z, 0-9, ?, !, =, _
34
+ x.gsub!(/([^ a-zA-Z0-9\_\?\!\=]+)/n, '_')
35
+
36
+ # if we get down to a nil or an empty string raise an exception!
37
+ raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
38
+
39
+ # condense multiple 'safe' non a-z chars to just one.
40
+ # ie. ___ becomes _ !!!! becomes ! etc...
41
+ [' ', '_', '?', '!', "="].each do |c|
42
+ x.squeeze!(c)
43
+ end
44
+
45
+ # if we get down to a nil or an empty string raise an exception!
46
+ raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
47
+
48
+ #down case the whole thing
49
+ x.downcase!
50
+
51
+ # get rid of any characters at the beginning that aren't a-z
52
+ while !x.match(/^[a-z]/)
53
+ x.slice!(0)
54
+
55
+ # if we get down to a nil or an empty string raise an exception!
56
+ raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
57
+ end
58
+
59
+ # let's trim this bad boy down a bit now that we've cleaned it up, somewhat.
60
+ # we should do this before cleaning up the end character, because it's possible to end up with a
61
+ # bad char at the end if you trim too late.
62
+ x = x[0..100] if x.length > 100
63
+
64
+ # get rid of any characters at the end that aren't safe
65
+ while !x.match(/[a-z0-9\?\!\=]$/)
66
+ x.slice!(x.length - 1)
67
+ # if we get down to a nil or an empty string raise an exception!
68
+ raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
69
+ end
70
+
71
+ # if we get down to a nil or an empty string raise an exception!
72
+ raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
73
+
74
+ # let's get rid of characters that don't belong in the 'middle' of the method.
75
+ orig_middle = x[1..(x.length - 2)]
76
+ n_middle = orig_middle.dup
77
+
78
+ ['?', '!', "="].each do |c|
79
+ n_middle.gsub!(c, "_")
80
+ end
81
+
82
+ # the previous gsub can leave us with multiple underscores that need cleaning up.
83
+ n_middle.squeeze!("_")
84
+
85
+ x.gsub!(orig_middle, n_middle)
86
+ x.gsub!("_=", "=")
87
+ x
88
+ end
89
+
90
+ 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,283 @@
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 heirarchy
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.compact!
27
+ path.reverse!
28
+ path.join('.')
29
+ end
30
+
31
+ def configatron_keys
32
+ return @_store.keys.collect{|k| k.to_s}.sort
33
+ end
34
+
35
+ # Checks whether or not a parameter exists
36
+ #
37
+ # Examples:
38
+ # configatron.i.am.alive = 'alive!'
39
+ # configatron.i.am.exists?(:alive) # => true
40
+ # configatron.i.am.exists?(:dead) # => false
41
+ def exists?(name)
42
+ @_store.has_key?(name.to_sym) || @_store.has_key?(name.to_s)
43
+ end
44
+
45
+ def inspect
46
+ path = [@_name]
47
+ parent = @_parent
48
+ until parent.nil?
49
+ path << parent.instance_variable_get('@_name')
50
+ parent = parent.instance_variable_get('@_parent')
51
+ end
52
+ path << 'configatron'
53
+ path.compact!
54
+ path.reverse!
55
+ f_out = []
56
+ @_store.each do |k, v|
57
+ if v.is_a?(Configatron::Store)
58
+ v.inspect.each_line do |line|
59
+ if line.match(/\n/)
60
+ line.each_line do |l|
61
+ l.strip!
62
+ f_out << l
63
+ end
64
+ else
65
+ line.strip!
66
+ f_out << line
67
+ end
68
+ end
69
+ else
70
+ f_out << "#{path.join('.')}.#{k} = #{v.inspect}"
71
+ end
72
+ end
73
+ f_out.compact.sort.join("\n")
74
+ end
75
+
76
+ # Allows for the configuration of the system via a Hash
77
+ def configure_from_hash(options)
78
+ parse_options(options)
79
+ end
80
+
81
+ # Allows for the configuration of the system from a YAML file.
82
+ # Takes the path to the YAML file. Also takes an optional parameter,
83
+ # <tt>:hash</tt>, that indicates a specific hash that should be
84
+ # loaded from the file.
85
+ def configure_from_yaml(path, opts = {})
86
+ begin
87
+ yml = ::Yamler.load(path)
88
+ yml = yml[opts[:hash]] unless opts[:hash].nil?
89
+ configure_from_hash(yml)
90
+ rescue Errno::ENOENT => e
91
+ puts e.message
92
+ end
93
+ end
94
+
95
+ # Returns true if there are no configuration parameters
96
+ def nil?
97
+ return @_store.empty?
98
+ end
99
+
100
+ # Retrieves a certain parameter and if that parameter
101
+ # doesn't exist it will return the default_value specified.
102
+ def retrieve(name, default_value = nil)
103
+ @_store[name.to_sym] || default_value
104
+ end
105
+
106
+ # Removes a parameter. In the case of a nested parameter
107
+ # it will remove all below it.
108
+ def remove(name)
109
+ @_store.delete(name.to_sym)
110
+ end
111
+
112
+ # Sets a 'default' value. If there is already a value specified
113
+ # it won't set the value.
114
+ def set_default(name, default_value)
115
+ unless @_store[name.to_sym]
116
+ @_store[name.to_sym] = parse_options(default_value)
117
+ end
118
+ end
119
+
120
+ def method_missing(sym, *args) # :nodoc:
121
+ if sym.to_s.match(/(.+)=$/)
122
+ name = sym.to_s.gsub("=", '').to_sym
123
+ raise Configatron::ProtectedParameter.new(name) if @_protected.include?(name) || methods_include?(name)
124
+ raise Configatron::LockedNamespace.new(@_name) if @_locked && !@_store.has_key?(name)
125
+ @_store[name] = parse_options(*args)
126
+ elsif @_store.has_key?(sym)
127
+ return @_store[sym]
128
+ else
129
+ store = Configatron::Store.new({}, sym, self)
130
+ @_store[sym] = store
131
+ return store
132
+ end
133
+ end
134
+
135
+ def ==(other) # :nodoc:
136
+ self.to_hash == other
137
+ end
138
+
139
+ # Prevents a parameter from being reassigned. If called on a 'namespace' then
140
+ # all parameters below it will be protected as well.
141
+ def protect(name)
142
+ @_protected << name.to_sym
143
+ end
144
+
145
+ # Prevents all parameters from being reassigned.
146
+ def protect_all!
147
+ @_protected.clear
148
+ @_store.keys.each do |k|
149
+ val = self.send(k)
150
+ val.protect_all! if val.class == Configatron::Store
151
+ @_protected << k
152
+ end
153
+ end
154
+
155
+ # Removes the protection of a parameter.
156
+ def unprotect(name)
157
+ @_protected.reject! { |e| e == name.to_sym }
158
+ end
159
+
160
+ def unprotect_all!
161
+ @_protected.clear
162
+ @_store.keys.each do |k|
163
+ val = self.send(k)
164
+ val.unprotect_all! if val.class == Configatron::Store
165
+ end
166
+ end
167
+
168
+ # Prevents a namespace from having new parameters set. The lock is applied
169
+ # recursively to any namespaces below it.
170
+ def lock(name)
171
+ namespace = @_store[name.to_sym]
172
+ raise ArgumentError, "Namespace #{name.inspect} does not exist" if namespace.nil?
173
+ namespace.lock!
174
+ end
175
+
176
+ def unlock(name)
177
+ namespace = @_store[name.to_sym]
178
+ raise ArgumentError, "Namespace #{name.inspect} does not exist" if namespace.nil?
179
+ namespace.unlock!
180
+ end
181
+
182
+ # = DeepClone
183
+ #
184
+ # == Version
185
+ # 1.2006.05.23 (change of the first number means Big Change)
186
+ #
187
+ # == Description
188
+ # Adds deep_clone method to an object which produces deep copy of it. It means
189
+ # if you clone a Hash, every nested items and their nested items will be cloned.
190
+ # Moreover deep_clone checks if the object is already cloned to prevent endless recursion.
191
+ #
192
+ # == Usage
193
+ #
194
+ # (see examples directory under the ruby gems root directory)
195
+ #
196
+ # require 'rubygems'
197
+ # require 'deep_clone'
198
+ #
199
+ # include DeepClone
200
+ #
201
+ # obj = []
202
+ # a = [ true, false, obj ]
203
+ # b = a.deep_clone
204
+ # obj.push( 'foo' )
205
+ # p obj # >> [ 'foo' ]
206
+ # p b[2] # >> []
207
+ #
208
+ # == Source
209
+ # http://simplypowerful.1984.cz/goodlibs/1.2006.05.23
210
+ #
211
+ # == Author
212
+ # jan molic (/mig/at_sign/1984/dot/cz/)
213
+ #
214
+ # == Licence
215
+ # You can redistribute it and/or modify it under the same terms of Ruby's license;
216
+ # either the dual license version in 2003, or any later version.
217
+ #
218
+ def deep_clone( obj=self, cloned={} )
219
+ if cloned.has_key?( obj.object_id )
220
+ return cloned[obj.object_id]
221
+ else
222
+ begin
223
+ cl = obj.clone
224
+ rescue Exception
225
+ # unclonnable (TrueClass, Fixnum, ...)
226
+ cloned[obj.object_id] = obj
227
+ return obj
228
+ else
229
+ cloned[obj.object_id] = cl
230
+ cloned[cl.object_id] = cl
231
+ if cl.is_a?( Hash )
232
+ cl.clone.each { |k,v|
233
+ cl[k] = deep_clone( v, cloned )
234
+ }
235
+ elsif cl.is_a?( Array )
236
+ cl.collect! { |v|
237
+ deep_clone( v, cloned )
238
+ }
239
+ end
240
+ cl.instance_variables.each do |var|
241
+ v = cl.instance_eval( var.to_s )
242
+ v_cl = deep_clone( v, cloned )
243
+ cl.instance_eval( "#{var} = v_cl" )
244
+ end
245
+ return cl
246
+ end
247
+ end
248
+ end
249
+
250
+ protected
251
+ def lock!
252
+ @_locked = true
253
+ @_store.values.each { |store| store.lock! if store.is_a?(Configatron::Store) }
254
+ end
255
+
256
+ def unlock!
257
+ @_locked = false
258
+ @_store.values.each { |store| store.unlock! if store.is_a?(Configatron::Store) }
259
+ end
260
+
261
+ private
262
+ def methods_include?(name)
263
+ self.methods.include?(RUBY_VERSION > '1.9.0' ? name.to_sym : name.to_s)
264
+ end
265
+
266
+ def parse_options(options)
267
+ if options.is_a?(Hash)
268
+ options.each do |k,v|
269
+ if v.is_a?(Hash)
270
+ self.method_missing(k.to_sym).configure_from_hash(v)
271
+ else
272
+ self.method_missing("#{k.to_sym}=", v)
273
+ end
274
+ end
275
+ else
276
+ return options
277
+ end
278
+ end
279
+
280
+ undef :test # :nodoc:
281
+
282
+ end # Store
283
+ end # Configatron
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: markbates-configatron
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.3.2.20090731133933
5
+ platform: ruby
6
+ authors:
7
+ - markbates
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-31 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: yamler
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.0
24
+ version:
25
+ description: "configatron was developed by: markbates"
26
+ email: mark@markbates.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ - LICENSE
34
+ files:
35
+ - lib/configatron/configatron.rb
36
+ - lib/configatron/core_ext/class.rb
37
+ - lib/configatron/core_ext/kernel.rb
38
+ - lib/configatron/core_ext/object.rb
39
+ - lib/configatron/core_ext/string.rb
40
+ - lib/configatron/errors.rb
41
+ - lib/configatron/store.rb
42
+ - lib/configatron.rb
43
+ - README
44
+ - LICENSE
45
+ has_rdoc: false
46
+ homepage: http://www.metabates.com
47
+ licenses:
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project: magrathea
68
+ rubygems_version: 1.3.5
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: A powerful Ruby configuration system.
72
+ test_files: []
73
+