markbates-configatron 2.3.2.20090731133933

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/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
+