configatron 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,77 @@
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 do |config|
9
+ config.email = "mark@mackframework.com"
10
+ config.database_url = "postgres://localhost/mack_framework_rocks"
11
+ # etc...
12
+ end
13
+
14
+ Now, anywhere in your code you can do the following:
15
+
16
+ configatron.email # => "mark@mackframework.com"
17
+ configatron.database_url # => "postgres://localhost/mack_framework_rocks"
18
+
19
+ Viola! Simple as can be.
20
+
21
+ 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:
22
+
23
+ configatron do |config|
24
+ config.database_url = "postgres://localhost/mack_framework_rocks_development"
25
+ end
26
+
27
+ becomes:
28
+
29
+ configatron.email # => "mark@mackframework.com"
30
+ configatron.database_url # => "postgres://localhost/mack_framework_rocks_development"
31
+
32
+ Notice how our other configuration parameters haven't changed? Cool, eh?
33
+
34
+ ===Namespaces
35
+
36
+ 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.
37
+
38
+ configatron do |config|
39
+ config.website_url = "http://www.mackframework.com"
40
+ config.email do |email|
41
+ email.pop do |pop|
42
+ pop.address = "pop.example.com"
43
+ pop.port = "110"
44
+ # etc ...
45
+ end
46
+ email.smtp do |smtp|
47
+ smtp.address = "smtp.example.com"
48
+ smtp.port = "25"
49
+ # etc ...
50
+ end
51
+ end
52
+ # etc...
53
+ end
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
+ Enjoy!
64
+
65
+ ==Contact
66
+ Please mail bugs, suggestions and patches to <bugs@mackframework.com>.
67
+
68
+ On the web at: http://www.mackframework.com
69
+
70
+ ==License and Copyright
71
+ Copyright (C) 2008 Mark Bates, http://www.mackframework.com
72
+
73
+ 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:
74
+
75
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
76
+
77
+ 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,8 @@
1
+ require 'singleton'
2
+ require File.join(File.dirname(__FILE__), 'helpers')
3
+ require File.join(File.dirname(__FILE__), 'kernel')
4
+ require File.join(File.dirname(__FILE__), 'configuration')
5
+ require File.join(File.dirname(__FILE__), 'store')
6
+
7
+ module Configatron # :nodoc:
8
+ end
@@ -0,0 +1,91 @@
1
+ module Configatron
2
+ # The central class for managing the configurations.
3
+ class Configuration
4
+ include Singleton
5
+ include Configatron::Helpers
6
+
7
+ # If nil_for_missing is set to true nil will be returned if the configuration
8
+ # parameter doesn't exist. If set to false, default, then a NoMethodError exception
9
+ # will be raised.
10
+ attr_accessor :nil_for_missing
11
+
12
+ def initialize # :nodoc:
13
+ @_storage_list = []
14
+ @_nil_for_missing = false
15
+ end
16
+
17
+ # Yields a new Configatron::Store class.
18
+ def configure
19
+ storage = Configatron::Store.new
20
+ yield storage
21
+ unless storage.parameters.empty?
22
+ @_storage_list << storage
23
+ load_methods(storage)
24
+ end
25
+ end
26
+
27
+ # Used to load configuration settings from a Hash.
28
+ def configure_from_hash(parameters)
29
+ storage = Configatron::Store.new(parameters)
30
+ @_storage_list << storage
31
+ load_methods(storage)
32
+ end
33
+
34
+ # Replays the history of configurations.
35
+ def reload
36
+ @_storage_list.each do |storage|
37
+ load_methods(storage)
38
+ end
39
+ end
40
+
41
+ # Does a hard reset of the Configatron::Configuration class.
42
+ # All methods are undefined, the list of configuration parameters
43
+ # is emptied, and the nil_for_missing method gets reset to false.
44
+ def reset!
45
+ reset
46
+ self.nil_for_missing = false
47
+ @_storage_list = []
48
+ end
49
+
50
+ # All methods are undefined.
51
+ def reset
52
+ @_storage_list.each do |storage|
53
+ storage.parameters.each do |k,v|
54
+ Configatron::Configuration.instance_eval do
55
+ begin
56
+ undef_method(k)
57
+ rescue NameError => e
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # Peels back n number of configuration parameters.
65
+ def revert(step = 1)
66
+ reset
67
+ step.times {@_storage_list.pop}
68
+ reload
69
+ end
70
+
71
+ def method_missing(sym, *args)
72
+ handle_missing_parameter(sym)
73
+ end
74
+
75
+ private
76
+ def load_methods(store)
77
+ store.parameters.each do |k,v|
78
+ if k.is_a?(Configatron::Store)
79
+ load_methods(k)
80
+ else
81
+ Configatron::Configuration.instance_eval do
82
+ define_method(k) do
83
+ v
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ end # Configuration
91
+ end # Configatron
data/lib/helpers.rb ADDED
@@ -0,0 +1,23 @@
1
+ module Configatron
2
+ module Helpers
3
+
4
+ def exists?(name)
5
+ self.respond_to?(name)
6
+ end
7
+
8
+ def handle_missing_parameter(param)
9
+ if configatron.nil_for_missing
10
+ return nil
11
+ else
12
+ raise NoMethodError.new(param.to_s)
13
+ end
14
+ end
15
+
16
+ def retrieve(name, default_value = ArgumentError)
17
+ return self.send(name) if exists?(name)
18
+ return default_value unless default_value == ArgumentError
19
+ handle_missing_parameter(name)
20
+ end
21
+
22
+ end # Helpers
23
+ end # Configatron
data/lib/kernel.rb ADDED
@@ -0,0 +1,14 @@
1
+ module Kernel
2
+
3
+ # If called without a block it will return the Configatron::Configuration instance.
4
+ # If called with a block then it will call the Configatron::Configatron configure method
5
+ # and yield up a Configatron::Store object.
6
+ def configatron(&block)
7
+ if block_given?
8
+ Configatron::Configuration.instance.configure(&block)
9
+ else
10
+ Configatron::Configuration.instance
11
+ end
12
+ end
13
+
14
+ end
data/lib/store.rb ADDED
@@ -0,0 +1,48 @@
1
+ module Configatron
2
+ # Used to store each of the 'sets' of configuration parameters.
3
+ class Store
4
+ include Configatron::Helpers
5
+
6
+ # The actual key/pair parameter values.
7
+ attr_reader :parameters
8
+
9
+ # Takes an optional Hash to configure parameters.
10
+ def initialize(parameters = {})
11
+ @parameters = parameters
12
+ end
13
+
14
+ # If a method is called with an = at the end, then that method name, minus
15
+ # the equal sign is added to the parameter list as a key, and it's *args
16
+ # become the value for that key. Eventually the keys become method names.
17
+ # If a method is called without an = sign at the end then the value from
18
+ # the parameters hash is returned, if it exists.
19
+ def method_missing(sym, *args)
20
+ if sym.to_s.match(/(.+)=$/)
21
+ @parameters[sym.to_s.gsub("=", '').to_sym] = *args
22
+ else
23
+ val = @parameters[sym]
24
+ return val unless val.nil?
25
+ return handle_missing_parameter(sym)
26
+ end
27
+ end
28
+
29
+ def exists?(name)
30
+ return true unless @parameters[name.to_sym].nil?
31
+ super(name)
32
+ end
33
+
34
+ # Used to create 'namespaces' around a set of configuration parameters.
35
+ def namespace(name)
36
+ if exists?(name)
37
+ yield self.send(name.to_sym)
38
+ elsif configatron.exists?(name)
39
+ yield configatron.send(name.to_sym)
40
+ else
41
+ ns = Configatron::Store.new
42
+ yield ns
43
+ @parameters[name.to_sym] = ns
44
+ end
45
+ end
46
+
47
+ end # Store
48
+ end # Configatron
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'pathname'
3
+ require 'spec'
4
+ require Pathname(__FILE__).dirname.parent.expand_path + 'lib/configatron'
@@ -0,0 +1,145 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ describe Configatron::Configuration do
5
+
6
+ before :each do
7
+ configatron.reset!
8
+ end
9
+
10
+ it "should be a Singleton" do
11
+ lambda{Configatron::Configuration.new}.should raise_error(NoMethodError)
12
+ Configatron::Configuration.instance.should == Configatron::Configuration.instance
13
+ end
14
+
15
+ describe "configure_from_hash" do
16
+
17
+ it "should take a Hash with the same outcome as the configure method" do
18
+ configatron.should_not respond_to(:bart)
19
+ configatron.should_not respond_to(:homer)
20
+
21
+ configatron.configure_from_hash(:bart => "Bart Simpson", "homer" => "Homer Simpson")
22
+
23
+ configatron.should respond_to(:bart)
24
+ configatron.should respond_to(:homer)
25
+
26
+ configatron.bart.should == "Bart Simpson"
27
+ configatron.homer.should == "Homer Simpson"
28
+ end
29
+
30
+ end
31
+
32
+ describe "revert" do
33
+
34
+ it "should roll back 1 level by default" do
35
+ configatron.should_not respond_to(:bart)
36
+ configatron.should_not respond_to(:homer)
37
+
38
+ configatron do |config|
39
+ config.bart = "Bart Simpson"
40
+ end
41
+ configatron do |config|
42
+ config.homer = "Homer Simpson"
43
+ end
44
+
45
+ configatron.should respond_to(:bart)
46
+ configatron.should respond_to(:homer)
47
+
48
+ configatron.bart.should == "Bart Simpson"
49
+ configatron.homer.should == "Homer Simpson"
50
+
51
+ configatron.revert
52
+
53
+ configatron.should respond_to(:bart)
54
+ configatron.should_not respond_to(:homer)
55
+ configatron.bart.should == "Bart Simpson"
56
+ lambda{configatron.homer}.should raise_error(NoMethodError)
57
+ end
58
+
59
+ it "should roll back n levels if specified" do
60
+ configatron.should_not respond_to(:bart)
61
+ configatron.should_not respond_to(:homer)
62
+
63
+ configatron do |config|
64
+ config.bart = "Bart Simpson"
65
+ end
66
+ configatron do |config|
67
+ config.homer = "Homer Simpson"
68
+ end
69
+
70
+ configatron.should respond_to(:bart)
71
+ configatron.should respond_to(:homer)
72
+
73
+ configatron.bart.should == "Bart Simpson"
74
+ configatron.homer.should == "Homer Simpson"
75
+
76
+ configatron.revert(2)
77
+
78
+ configatron.should_not respond_to(:bart)
79
+ configatron.should_not respond_to(:homer)
80
+ lambda{configatron.bart}.should raise_error(NoMethodError)
81
+ lambda{configatron.homer}.should raise_error(NoMethodError)
82
+ end
83
+
84
+ end
85
+
86
+ describe "reset" do
87
+
88
+ it "should remove all added methods" do
89
+ configatron.should_not respond_to(:rst1)
90
+ configatron.should_not respond_to(:rst2)
91
+
92
+ configatron.nil_for_missing.should == false
93
+
94
+ configatron do |config|
95
+ config.rst1 = "RST1"
96
+ config.rst2 = "RST2"
97
+ end
98
+
99
+ configatron.should respond_to(:rst1)
100
+ configatron.should respond_to(:rst2)
101
+
102
+ configatron.nil_for_missing = true
103
+ configatron.nil_for_missing.should == true
104
+
105
+ configatron.reset
106
+
107
+ configatron.nil_for_missing.should == true
108
+
109
+ configatron.should_not respond_to(:rst1)
110
+ configatron.should_not respond_to(:rst2)
111
+
112
+ end
113
+
114
+ end
115
+
116
+ describe "reset!" do
117
+
118
+ it "should remove all added methods and revert the nil_for_missing setting" do
119
+ configatron.should_not respond_to(:rst1)
120
+ configatron.should_not respond_to(:rst2)
121
+
122
+ configatron.nil_for_missing.should == false
123
+
124
+ configatron do |config|
125
+ config.rst1 = "RST1"
126
+ config.rst2 = "RST2"
127
+ end
128
+
129
+ configatron.should respond_to(:rst1)
130
+ configatron.should respond_to(:rst2)
131
+
132
+ configatron.nil_for_missing = true
133
+ configatron.nil_for_missing.should == true
134
+
135
+ configatron.reset!
136
+
137
+ configatron.nil_for_missing.should == false
138
+
139
+ configatron.should_not respond_to(:rst1)
140
+ configatron.should_not respond_to(:rst2)
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,115 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ describe Configatron::Helpers do
5
+
6
+ before :each do
7
+ configatron.reset!
8
+ end
9
+
10
+ describe "exists?" do
11
+
12
+ it "should return true or false if the configuration parameter exists" do
13
+
14
+ configatron.exists?(:foo).should == false
15
+ configatron.exists?(:email).should == false
16
+
17
+ configatron do |config|
18
+ config.foo = :bar
19
+ config.namespace(:email) do |email|
20
+ email.address = "mark@mackframework.com"
21
+ end
22
+ end
23
+
24
+ configatron.exists?(:foo).should == true
25
+ configatron.exists?(:email).should == true
26
+ configatron.email.exists?(:address).should == true
27
+ configatron.email.exists?(:server).should == false
28
+
29
+ end
30
+
31
+ end
32
+
33
+ describe "retrieve" do
34
+
35
+ before :each do
36
+ configatron do |config|
37
+ config.foo = :bar
38
+ config.namespace(:email) do |email|
39
+ email.address = "mark@mackframework.com"
40
+ end
41
+ end
42
+ end
43
+
44
+ it "should return a valid parameter" do
45
+ configatron.retrieve(:foo).should == :bar
46
+ configatron.email.retrieve(:address).should == "mark@mackframework.com"
47
+ end
48
+
49
+ it "should return a default value if one is specified" do
50
+ configatron.retrieve(:name, "mark").should == "mark"
51
+ configatron.email.retrieve(:server, "pop3.example.com").should == "pop3.example.com"
52
+ end
53
+
54
+ it "should behave like a standard missing parameter if no default value is specified" do
55
+ lambda{configatron.retrieve(:name)}.should raise_error(NoMethodError)
56
+ lambda{configatron.email.retrieve(:name)}.should raise_error(NoMethodError)
57
+ end
58
+
59
+ it "should return nil if the default value is nil" do
60
+ configatron.retrieve(:name, nil).should == nil
61
+ end
62
+
63
+ it "should work!" do
64
+ require 'logger'
65
+ configatron do |config|
66
+ config.namespace(:mack) do |mack|
67
+ mack.render_url_timeout = 5
68
+ mack.cache_classes = true
69
+ mack.use_lint = true
70
+ mack.show_exceptions = true
71
+ mack.session_id = "_mack_session_id"
72
+ mack.cookie_values = {
73
+ "path" => "/"
74
+ }
75
+ mack.site_domain = "http://localhost:3000"
76
+ mack.use_distributed_routes = false
77
+ mack.distributed_app_name = nil
78
+ mack.drb_timeout = 1
79
+ mack.default_respository_name = "default"
80
+ end
81
+ config.namespace(:cachetastic_default_options) do |cache|
82
+ cache.debug = false
83
+ cache.adapter = :local_memory
84
+ logger = ::Logger.new(STDOUT)
85
+ logger.level = ::Logger::INFO
86
+ cache.logger = logger
87
+ end
88
+ config.namespace(:log) do |log|
89
+ log.detailed_requests = true
90
+ log.level = :info
91
+ log.console = false
92
+ log.file = true
93
+ log.console_format = "%l:\t[%d]\t%M"
94
+ log.file_format = "%l:\t[%d]\t%M"
95
+ end
96
+ end
97
+ configatron do |config|
98
+ config.namespace(:mack) do |mack|
99
+ mack.drb_timeout = 0
100
+ mack.cookie_values = {}
101
+ end
102
+ config.namespace(:log) do |log|
103
+ log.level = :error
104
+ end
105
+ config.run_remote_tests = true
106
+ end
107
+
108
+ configatron.log.retrieve(:file, false).should == true
109
+ configatron.log.file.should == true
110
+
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,48 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ describe Kernel do
5
+
6
+ it "should have a configatron method" do
7
+ configatron
8
+ end
9
+
10
+ describe "configatron" do
11
+
12
+ before :each do
13
+ configatron.reset!
14
+ end
15
+
16
+ it "should raise NoMethodError if the parameter doesn't exist" do
17
+ lambda{configatron.i_dont_exist}.should raise_error(NoMethodError)
18
+ end
19
+
20
+ it "should return nil if nil_for_missing is set to true" do
21
+ configatron.nil_for_missing = true
22
+ configatron.i_dont_exist.should == nil
23
+ end
24
+
25
+ it "should take a block that allows for the configuration of the configatron system" do
26
+ lambda{configatron.foo}.should raise_error(NoMethodError)
27
+ configatron do |config|
28
+ config.foo = :bar
29
+ config.say_hello = "Hello World"
30
+ end
31
+ configatron.foo.should == :bar
32
+ configatron.say_hello == "Hello World"
33
+ end
34
+
35
+ it "should allow previously defined parameters to be redefined" do
36
+ configatron do |config|
37
+ config.foo = :bar
38
+ end
39
+ configatron.foo.should == :bar
40
+ configatron do |config|
41
+ config.foo = "fubar"
42
+ end
43
+ configatron.foo.should == "fubar"
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,68 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ describe Configatron::Store do
5
+
6
+ before :each do
7
+ configatron.reset!
8
+ end
9
+
10
+ describe "namespace" do
11
+
12
+ it "should let you 'namespace' a set of configuration parameters" do
13
+ lambda{configatron.foo}.should raise_error(NoMethodError)
14
+ configatron do |config|
15
+ config.namespace(:foo) do |foo|
16
+ foo.bar = :bar
17
+ end
18
+ end
19
+ configatron.foo.bar.should == :bar
20
+ end
21
+
22
+ it "should raise NoMethodError if nil_for_missing is set to false" do
23
+ lambda{configatron.foo}.should raise_error(NoMethodError)
24
+ configatron do |config|
25
+ config.namespace(:foo) do |foo|
26
+ foo.bar = :bar
27
+ end
28
+ end
29
+ lambda{configatron.foo.say_hello}.should raise_error(NoMethodError)
30
+ end
31
+
32
+ it "should allow for unlimited nested namespaces" do
33
+ configatron do |config|
34
+ config.namespace(:foo) do |foo|
35
+ foo.bar = :bar
36
+ foo.namespace(:apples) do |apps|
37
+ apps.granny_smith = "Granny Smith"
38
+ apps.red = "Red"
39
+ end
40
+ end
41
+ end
42
+ configatron.foo.bar.should == :bar
43
+ configatron.foo.apples.granny_smith.should == "Granny Smith"
44
+ end
45
+
46
+ it "should not override all parameters when you namespace" do
47
+ configatron do |config|
48
+ config.namespace(:foo) do |foo|
49
+ foo.bar = :bar
50
+ foo.name = "mark"
51
+ end
52
+ end
53
+ configatron.foo.bar.should == :bar
54
+ configatron.foo.name.should == "mark"
55
+
56
+ configatron do |config|
57
+ config.namespace(:foo) do |foo|
58
+ foo.name = "mark bates"
59
+ end
60
+ end
61
+
62
+ configatron.foo.bar.should == :bar
63
+ configatron.foo.name.should == "mark bates"
64
+ end
65
+
66
+ end
67
+
68
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: configatron
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - markbates
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-29 00:00:00 -04: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.rb
26
+ - lib/configuration.rb
27
+ - lib/helpers.rb
28
+ - lib/kernel.rb
29
+ - lib/store.rb
30
+ - README
31
+ has_rdoc: true
32
+ homepage: http://www.mackframework.com
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ requirements: []
52
+
53
+ rubyforge_project: magrathea
54
+ rubygems_version: 1.2.0
55
+ signing_key:
56
+ specification_version: 2
57
+ summary: A powerful Ruby configuration system.
58
+ test_files:
59
+ - spec/spec.opts
60
+ - spec/spec_helper.rb
61
+ - spec/unit
62
+ - spec/unit/configuration_spec.rb
63
+ - spec/unit/helpers_spec.rb
64
+ - spec/unit/kernel_spec.rb
65
+ - spec/unit/store_spec.rb