configr 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/examples/all.rb +73 -0
- data/lib/configr/configuration.rb +61 -0
- data/lib/configr/configuration_block.rb +27 -0
- data/lib/configr/errors.rb +13 -0
- data/lib/configr/hash.rb +49 -0
- data/lib/configr.rb +4 -0
- data/readme.rdoc +137 -0
- data/spec/fixtures/configuration.yml +2 -0
- data/spec/lib/configuration_block_spec.rb +52 -0
- data/spec/lib/configuration_spec.rb +127 -0
- data/spec/lib/errors_spec.rb +13 -0
- data/spec/lib/hash_spec.rb +66 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/watch.rb +28 -0
- metadata +86 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Josh Nesbitt <josh@josh-nesbitt.net>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "configr"
|
8
|
+
gem.summary = "A more Rubyish approach to creating and accessing configuration values."
|
9
|
+
gem.description = "Configr aims to provide a more Ruby-like interface to configuring and reading a set of configuration values. The idea evolved from using a standard hash as a configuration store into a more elegant way to declare and read values from within a hash. "
|
10
|
+
gem.email = "josh@josh-nesbitt.net"
|
11
|
+
gem.homepage = "http://github.com/joshnesbitt/configr"
|
12
|
+
gem.authors = ["Josh Nesbitt"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'spec/rake/spectask'
|
21
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
22
|
+
spec.libs << 'lib' << 'spec'
|
23
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
24
|
+
end
|
25
|
+
|
26
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
27
|
+
spec.libs << 'lib' << 'spec'
|
28
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
29
|
+
spec.rcov = true
|
30
|
+
end
|
31
|
+
|
32
|
+
task :spec => :check_dependencies
|
33
|
+
task :default => :spec
|
34
|
+
|
35
|
+
require 'rake/rdoctask'
|
36
|
+
Rake::RDocTask.new do |rdoc|
|
37
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
38
|
+
|
39
|
+
rdoc.rdoc_dir = 'rdoc'
|
40
|
+
rdoc.title = "configurable #{version}"
|
41
|
+
rdoc.rdoc_files.include('README*')
|
42
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
43
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/examples/all.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'configr'))
|
2
|
+
|
3
|
+
# Standalone (without YAML)
|
4
|
+
|
5
|
+
configuration = Configr::Configuration.configure do |config|
|
6
|
+
config.example_one = "One"
|
7
|
+
config.example_two = "Two"
|
8
|
+
end
|
9
|
+
|
10
|
+
puts configuration.example_one
|
11
|
+
puts configuration.example_two
|
12
|
+
puts configuration.doesnt_exist
|
13
|
+
|
14
|
+
|
15
|
+
# With YAML (inline)
|
16
|
+
|
17
|
+
yaml = <<YAML
|
18
|
+
|
19
|
+
example_one: "Oooooo"
|
20
|
+
example_two: "It loads from YAML too!"
|
21
|
+
|
22
|
+
YAML
|
23
|
+
|
24
|
+
configuration = Configr::Configuration.configure(yaml)
|
25
|
+
|
26
|
+
puts configuration.example_one
|
27
|
+
puts configuration.example_two
|
28
|
+
|
29
|
+
|
30
|
+
# With YAML (file)
|
31
|
+
|
32
|
+
configuration = Configr::Configuration.configure(File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec', 'fixtures', 'configuration.yml')))
|
33
|
+
|
34
|
+
puts configuration.first_name
|
35
|
+
puts configuration.location
|
36
|
+
|
37
|
+
|
38
|
+
# Or go nuts (inline yaml and block)
|
39
|
+
|
40
|
+
yaml = <<YAML
|
41
|
+
|
42
|
+
example_three: "Oooooo"
|
43
|
+
example_four: "It loads from YAML too!"
|
44
|
+
|
45
|
+
YAML
|
46
|
+
|
47
|
+
configuration = Configr::Configuration.configure(yaml) do |config|
|
48
|
+
config.example_one = "One"
|
49
|
+
config.example_two = "Two"
|
50
|
+
end
|
51
|
+
|
52
|
+
puts configuration.example_one
|
53
|
+
puts configuration.example_two
|
54
|
+
puts configuration.example_three
|
55
|
+
puts configuration.example_four
|
56
|
+
|
57
|
+
# Good for things like this
|
58
|
+
|
59
|
+
Config = Configr::Configuration.configure do |config|
|
60
|
+
config.support_email = "goaway@example.com"
|
61
|
+
config.google_analytics = "UA-x343x-SDS"
|
62
|
+
|
63
|
+
config.twitter.screen_name = "someone"
|
64
|
+
config.twitter.password = "somepass"
|
65
|
+
end
|
66
|
+
|
67
|
+
puts Config.support_email
|
68
|
+
puts Config.google_analytics
|
69
|
+
puts Config.twitter[:screen_name]
|
70
|
+
puts Config.twitter[:password]
|
71
|
+
|
72
|
+
puts Config.twitter.screen_name
|
73
|
+
puts Config.twitter.password
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'hash'
|
3
|
+
require 'errors'
|
4
|
+
require 'configuration_block'
|
5
|
+
|
6
|
+
module Configr
|
7
|
+
class Configuration
|
8
|
+
attr_accessor :base, :attributes, :yaml
|
9
|
+
|
10
|
+
def initialize(yaml=nil)
|
11
|
+
self.base = ConfigurationBlock.new
|
12
|
+
self.yaml = yaml
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configure(yaml=nil)
|
16
|
+
instance = self.new(yaml)
|
17
|
+
|
18
|
+
yield instance.base if block_given?
|
19
|
+
|
20
|
+
instance.attributes = instance.base.attributes
|
21
|
+
|
22
|
+
instance.merge_configurations!
|
23
|
+
|
24
|
+
instance.attributes.recursive_normalize!
|
25
|
+
|
26
|
+
instance
|
27
|
+
end
|
28
|
+
|
29
|
+
def [](value)
|
30
|
+
self.attributes[value]
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(method, *args, &block)
|
34
|
+
name = method.to_s
|
35
|
+
|
36
|
+
case
|
37
|
+
when name.include?("=")
|
38
|
+
raise ConfigurationLocked, "Blocked from configuring values after configuration has been run."
|
39
|
+
when name.include?("?")
|
40
|
+
!self.attributes[name.gsub("?", "").to_sym].nil?
|
41
|
+
else
|
42
|
+
self.attributes[method.to_sym] or self.attributes[method.to_s]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def merge_configurations!
|
47
|
+
return unless self.yaml
|
48
|
+
|
49
|
+
hash = if File.exists?(self.yaml)
|
50
|
+
YAML.load_file(self.yaml)
|
51
|
+
else
|
52
|
+
YAML.load(self.yaml)
|
53
|
+
end
|
54
|
+
|
55
|
+
hash = Hash.new(hash)
|
56
|
+
hash.recursive_symbolize_keys!
|
57
|
+
|
58
|
+
self.attributes.merge!(hash)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Configr
|
2
|
+
class ConfigurationBlock
|
3
|
+
attr_accessor :attributes
|
4
|
+
|
5
|
+
def initialize(attributes={})
|
6
|
+
self.attributes = Hash.new(attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(method, *args, &block)
|
10
|
+
name = method.to_s
|
11
|
+
|
12
|
+
case
|
13
|
+
when name.include?('=')
|
14
|
+
key = name.gsub('=','').to_sym
|
15
|
+
self.attributes[key] = args.first
|
16
|
+
when existing_block_attributes = self.attributes[method]
|
17
|
+
existing_block = ConfigurationBlock.new(existing_block_attributes)
|
18
|
+
self.attributes[method] = existing_block.attributes
|
19
|
+
existing_block
|
20
|
+
else
|
21
|
+
nested_block = ConfigurationBlock.new
|
22
|
+
self.attributes[method] = nested_block.attributes
|
23
|
+
nested_block
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/configr/hash.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Configr
|
2
|
+
module HashExtensions
|
3
|
+
def symbolize_keys!
|
4
|
+
self.each { |k, v|
|
5
|
+
self.delete(k.to_s);
|
6
|
+
self[k.to_sym] = v
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
def recursive_symbolize_keys!
|
11
|
+
self.symbolize_keys!
|
12
|
+
self.values.select{ |value|
|
13
|
+
value.is_a?(::Hash) || value.is_a?(Hash)
|
14
|
+
}.each{ |hash|
|
15
|
+
hash.recursive_symbolize_keys!
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Hash < ::Hash
|
21
|
+
include HashExtensions
|
22
|
+
|
23
|
+
def initialize(hash)
|
24
|
+
hash ? hash.each_pair { |key, val| self.delete(key.to_s); self[key] = val } : self
|
25
|
+
end
|
26
|
+
|
27
|
+
def normalize!
|
28
|
+
recursive_symbolize_keys!
|
29
|
+
|
30
|
+
each_pair do |key, val|
|
31
|
+
self[key] = Hash.new(val) if val.is_a?(::Hash)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def recursive_normalize!
|
36
|
+
normalize!
|
37
|
+
values.select { |val| val.is_a?(::Hash) }.each { |hash| hash.recursive_normalize! }
|
38
|
+
end
|
39
|
+
|
40
|
+
def method_missing(method, *args, &block)
|
41
|
+
self[method]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Hash
|
47
|
+
include Configr::HashExtensions
|
48
|
+
|
49
|
+
end
|
data/lib/configr.rb
ADDED
data/readme.rdoc
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
= Configr
|
2
|
+
|
3
|
+
* Overview
|
4
|
+
* Installation
|
5
|
+
* Usage
|
6
|
+
* Usage (within frameworks)
|
7
|
+
* Contributors
|
8
|
+
|
9
|
+
== Overview
|
10
|
+
|
11
|
+
Configr aims to provide a more Ruby-like interface to configuring and reading a set of configuration values. The idea evolved from using a standard hash as a configuration store into a more elegant way to declare and read values from within a hash.
|
12
|
+
|
13
|
+
== Installation
|
14
|
+
|
15
|
+
The project is hosted on rubygems.org. Getting it is simple:
|
16
|
+
|
17
|
+
gem install <gem name>
|
18
|
+
|
19
|
+
== Usage
|
20
|
+
|
21
|
+
There are a variety of ways in which you can use Configr:
|
22
|
+
|
23
|
+
* Standalone block
|
24
|
+
* From inline YAML
|
25
|
+
* From a YAML file
|
26
|
+
* A mixture of YAML and block configuration
|
27
|
+
|
28
|
+
The following examples can also be found and run in examples/all.rb.
|
29
|
+
|
30
|
+
=== Standalone Block
|
31
|
+
|
32
|
+
configuration = Configr::Configuration.configure do |config|
|
33
|
+
config.example_one = "One"
|
34
|
+
config.example_two = "Two"
|
35
|
+
end
|
36
|
+
|
37
|
+
puts configuration.example_one
|
38
|
+
puts configuration.example_two
|
39
|
+
|
40
|
+
Conceptually you could continue to nest configuration blocks as far as you wish. They exist to enable you to seperate your configuration values into contexts. Take for example a set of email configuration values:
|
41
|
+
|
42
|
+
Configr::Configuration.configure do |config|
|
43
|
+
config.email.from_address = "hello@example.com"
|
44
|
+
config.email.from_name = "My Company"
|
45
|
+
config.email.reply_address = "reply@example.com"
|
46
|
+
end
|
47
|
+
|
48
|
+
=== From an inline YAML string
|
49
|
+
|
50
|
+
yaml = <<YAML
|
51
|
+
|
52
|
+
example_one: "Hello"
|
53
|
+
example_two: "It loads from YAML too!"
|
54
|
+
|
55
|
+
YAML
|
56
|
+
|
57
|
+
configuration = Configr::Configuration.configure(yaml)
|
58
|
+
|
59
|
+
puts configuration.example_one
|
60
|
+
puts configuration.example_two
|
61
|
+
|
62
|
+
=== From a YAML file
|
63
|
+
|
64
|
+
configuration = Configr::Configuration.configure("/path/to/file.yml")
|
65
|
+
|
66
|
+
puts configuration.value_one
|
67
|
+
puts configuration.value_two
|
68
|
+
|
69
|
+
=== A mixture of any of the above
|
70
|
+
|
71
|
+
yaml = <<YAML
|
72
|
+
|
73
|
+
example_three: "Oooooo"
|
74
|
+
example_four: "It loads from YAML too!"
|
75
|
+
|
76
|
+
YAML
|
77
|
+
|
78
|
+
configuration = Configr::Configuration.configure(yaml) do |config|
|
79
|
+
config.example_one = "One"
|
80
|
+
config.example_two = "Two"
|
81
|
+
end
|
82
|
+
|
83
|
+
puts configuration.example_one
|
84
|
+
puts configuration.example_two
|
85
|
+
puts configuration.example_three
|
86
|
+
puts configuration.example_four
|
87
|
+
|
88
|
+
== Usage (within frameworks)
|
89
|
+
|
90
|
+
Configr is intended to be framework agnostic, but it's easy to get it going within Rails/Sinatra/Hot New Framework app.
|
91
|
+
|
92
|
+
=== Rails
|
93
|
+
|
94
|
+
You can use Configr within Rails quite easily. I don't really plan to provide any "out of the box" way to hook Configr into Rails but it's quite easy to implement:
|
95
|
+
|
96
|
+
# In config/configuration.rb
|
97
|
+
Config = Configr::Configuration.configure(Rails.root.join("config", "environments", "#{Rails.env}.yml")) do |config|
|
98
|
+
config.my.configuration.value = "value"
|
99
|
+
end
|
100
|
+
|
101
|
+
# In config/initializers/configuration.rb
|
102
|
+
require Rails.root.join("config", "configuration.rb")
|
103
|
+
|
104
|
+
# Anywhere in your Rails app
|
105
|
+
Config.my.configuration.value
|
106
|
+
|
107
|
+
By requiring a different YAML file based on the environment it is easy to override global values with environment specific values.
|
108
|
+
|
109
|
+
=== Sinatra
|
110
|
+
|
111
|
+
A quick and dirty solution would be to pop it in a configure block:
|
112
|
+
|
113
|
+
configure do
|
114
|
+
Config = Configr::Configuration.configure(File.join("#{environment}.yml")) do |config|
|
115
|
+
config.something = "value"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
Again, by requiring a different YAML file based on the environment it is easy to override global values with environment specific values.
|
120
|
+
|
121
|
+
== Contributors
|
122
|
+
|
123
|
+
* Thomas Williams for the concept of nested configuration blocks.
|
124
|
+
|
125
|
+
== Note on Patches/Pull Requests
|
126
|
+
|
127
|
+
* Fork the project.
|
128
|
+
* Make your feature addition or bug fix.
|
129
|
+
* Add tests for it. This is important so I don't break it in a
|
130
|
+
future version unintentionally.
|
131
|
+
* Commit, do not mess with rakefile, version, or history.
|
132
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
133
|
+
* Send me a pull request. Bonus points for topic branches.
|
134
|
+
|
135
|
+
== Copyright
|
136
|
+
|
137
|
+
Copyright (c) 2010 Josh Nesbitt <josh@josh-nesbitt.net>. See LICENSE for details.
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Configr
|
2
|
+
describe ConfigurationBlock do
|
3
|
+
before do
|
4
|
+
@hash = { :one => "one", :two => "two" }
|
5
|
+
@block = ConfigurationBlock.new(@hash)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should convert a standard Hash to a Configr Hash on creation" do
|
9
|
+
@block.attributes.class.should == Configr::Hash
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should assign a value when the missing method looks likes a setter" do
|
13
|
+
@block.something = "value"
|
14
|
+
@block.something_else = "value"
|
15
|
+
|
16
|
+
@block.attributes[:something].should == "value"
|
17
|
+
@block.attributes[:something_else].should == "value"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should allow you to continue to create nested ConfigurationBlocks within each other" do
|
21
|
+
@block.something.else = "else"
|
22
|
+
@block.something.again = "again"
|
23
|
+
@block.something.nested.within = "within"
|
24
|
+
|
25
|
+
@block.attributes[:something][:else].should == "else"
|
26
|
+
@block.attributes[:something][:again].should == "again"
|
27
|
+
@block.attributes[:something][:nested][:within].should == "within"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return an existing block if an assignment is made within the same nested level" do
|
31
|
+
@block.first.second.var1 = "var1"
|
32
|
+
@block.first.second.var2 = "var2"
|
33
|
+
@block.first.second.var3 = "var3"
|
34
|
+
@block.first.second.var4 = "var4"
|
35
|
+
@block.first.second.var5 = "var5"
|
36
|
+
@block.first.second.var6 = "var6"
|
37
|
+
|
38
|
+
@block.attributes[:first][:second][:var1].should == "var1"
|
39
|
+
@block.attributes[:first][:second][:var2].should == "var2"
|
40
|
+
@block.attributes[:first][:second][:var3].should == "var3"
|
41
|
+
@block.attributes[:first][:second][:var4].should == "var4"
|
42
|
+
@block.attributes[:first][:second][:var5].should == "var5"
|
43
|
+
@block.attributes[:first][:second][:var6].should == "var6"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return a new ConfigurationBlock if that nested level has not been created yet" do
|
47
|
+
@block.five.class.should == ConfigurationBlock
|
48
|
+
@block.five.six.class.should == ConfigurationBlock
|
49
|
+
@block.five.six.seven.class.should == ConfigurationBlock
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Configr
|
2
|
+
describe Configuration do
|
3
|
+
|
4
|
+
it "should have the #configure class method to instantiate the configuration" do
|
5
|
+
Configuration.should respond_to(:configure)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should return nil when a value is not set" do
|
9
|
+
configuration = Configuration.configure do |config|
|
10
|
+
config.key = "value"
|
11
|
+
end
|
12
|
+
|
13
|
+
configuration.other_key.should be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return a value for a key when one has been set" do
|
17
|
+
configuration = Configuration.configure do |config|
|
18
|
+
config.key = "value"
|
19
|
+
end
|
20
|
+
|
21
|
+
configuration.key.should == "value"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise an error when an existing value attempts to be updated" do
|
25
|
+
configuration = Configuration.configure do |config|
|
26
|
+
config.key = "value"
|
27
|
+
end
|
28
|
+
|
29
|
+
lambda { configuration.key = "othervalue" }.should raise_error(Configr::ConfigurationLocked)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should report a value being present on #attribute?" do
|
33
|
+
configuration = Configuration.configure do |config|
|
34
|
+
config.key = "value"
|
35
|
+
end
|
36
|
+
|
37
|
+
configuration.key?.should == true
|
38
|
+
configuration.other_value?.should == false
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should load a configuration from a YAML string" do
|
42
|
+
yaml = <<-YAML
|
43
|
+
first_name: Josh
|
44
|
+
location: Leeds
|
45
|
+
YAML
|
46
|
+
|
47
|
+
configuration = Configuration.configure(yaml)
|
48
|
+
|
49
|
+
configuration.first_name.should == "Josh"
|
50
|
+
configuration.location.should == "Leeds"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should load a configuration from a YAML string and a block" do
|
54
|
+
yaml = <<-YAML
|
55
|
+
first_name: Josh
|
56
|
+
location: Leeds
|
57
|
+
YAML
|
58
|
+
|
59
|
+
configuration = Configuration.configure(yaml) do |config|
|
60
|
+
config.from_block = "value"
|
61
|
+
end
|
62
|
+
|
63
|
+
configuration.first_name.should == "Josh"
|
64
|
+
configuration.location.should == "Leeds"
|
65
|
+
configuration.from_block.should == "value"
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should load a configation from a YAML file" do
|
69
|
+
file = File.expand_path(File.join('spec', 'fixtures', 'configuration.yml'))
|
70
|
+
|
71
|
+
configuration = Configuration.configure(file)
|
72
|
+
|
73
|
+
configuration.first_name.should == "Bob"
|
74
|
+
configuration.location.should == "Somewhere else"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should load a configation from a YAML file and a block" do
|
78
|
+
file = File.expand_path(File.join('spec', 'fixtures', 'configuration.yml'))
|
79
|
+
|
80
|
+
configuration = Configuration.configure(file) do |config|
|
81
|
+
config.hello = "value"
|
82
|
+
end
|
83
|
+
|
84
|
+
configuration.first_name.should == "Bob"
|
85
|
+
configuration.location.should == "Somewhere else"
|
86
|
+
configuration.hello.should == "value"
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should allow a value from YAML to have precedence over the block" do
|
90
|
+
file = File.expand_path(File.join('spec', 'fixtures', 'configuration.yml'))
|
91
|
+
|
92
|
+
configuration = Configuration.configure(file) do |config|
|
93
|
+
config.first_name = "Billy"
|
94
|
+
end
|
95
|
+
|
96
|
+
configuration.first_name.should == "Bob"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should allow a deeply nested hash to be accessed with hash notation" do
|
100
|
+
configuration = Configuration.configure do |config|
|
101
|
+
config.one.two.three.four = "value"
|
102
|
+
end
|
103
|
+
|
104
|
+
configuration.one[:two][:three][:four].should == "value"
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should allow more than one value to be assigned within the same namespace" do
|
108
|
+
configuration = Configuration.configure do |config|
|
109
|
+
config.one.two.three.var1 = "value one"
|
110
|
+
config.one.two.three.var2 = "value two"
|
111
|
+
config.one.two.three.var3 = "value three"
|
112
|
+
end
|
113
|
+
|
114
|
+
configuration.one[:two][:three][:var1].should == "value one"
|
115
|
+
configuration.one[:two][:three][:var2].should == "value two"
|
116
|
+
configuration.one[:two][:three][:var3].should == "value three"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should allow method like lookup of attributes" do
|
120
|
+
configuration = Configuration.configure do |config|
|
121
|
+
config.one.two.three.var1 = "value"
|
122
|
+
end
|
123
|
+
|
124
|
+
configuration.one.two.three.var1.should == "value"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Configr
|
2
|
+
describe Hash do
|
3
|
+
|
4
|
+
it "should have a base error class defined for Configr" do
|
5
|
+
Configr::ConfigrError.ancestors.should include(StandardError)
|
6
|
+
|
7
|
+
error = Configr::ConfigrError.new("Error data")
|
8
|
+
|
9
|
+
error.data.should == "Error data"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Configr
|
2
|
+
describe Hash do
|
3
|
+
|
4
|
+
it "should create a ConfigurableHash from an existing hash" do
|
5
|
+
hash = Hash.new({ :one => "one", :two => "two" })
|
6
|
+
|
7
|
+
hash[:one].should == "one"
|
8
|
+
hash[:two].should == "two"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should symbolize a set of string keys" do
|
12
|
+
hash = Hash.new({ "one" => "one", "two" => "two" })
|
13
|
+
|
14
|
+
hash[:one].should be_nil
|
15
|
+
hash[:two].should be_nil
|
16
|
+
|
17
|
+
hash.symbolize_keys!
|
18
|
+
|
19
|
+
hash[:one].should == "one"
|
20
|
+
hash[:two].should == "two"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should recursively symbolize a set of string keys" do
|
24
|
+
hash = Hash.new({ "one" => "one", "two" => "two", "three" => { "four" => "four" } })
|
25
|
+
|
26
|
+
hash[:one].should be_nil
|
27
|
+
hash[:two].should be_nil
|
28
|
+
hash[:three].should be_nil
|
29
|
+
|
30
|
+
hash.recursive_symbolize_keys!
|
31
|
+
|
32
|
+
hash[:one].should == "one"
|
33
|
+
hash[:two].should == "two"
|
34
|
+
hash[:three][:four].should == "four"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should normalize a set of Hash values to a Configr Hash if they are themselves Hashes" do
|
38
|
+
hash = Hash.new({ "one" => "one", "two" => "two", "three" => { "four" => "four" } })
|
39
|
+
|
40
|
+
hash["three"].class.should == ::Hash
|
41
|
+
|
42
|
+
hash.normalize!
|
43
|
+
|
44
|
+
hash[:three].class.should == Configr::Hash
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should recursively normalize a set of Hash values to a Configr Hash if they are themselves Hashes" do
|
48
|
+
hash = Hash.new({ "one" => "one", "two" => "two", "three" => { "four" => "four", "five" => { "six" => "six" } } })
|
49
|
+
|
50
|
+
hash["three"].class.should == ::Hash
|
51
|
+
hash["three"]["five"].class.should == ::Hash
|
52
|
+
|
53
|
+
hash.recursive_normalize!
|
54
|
+
|
55
|
+
hash[:three].class.should == Configr::Hash
|
56
|
+
hash[:three][:five].class.should == Configr::Hash
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should utilise method missing to provide access to hash keys" do
|
60
|
+
hash = Hash.new({ :one => "one", :two => "two" })
|
61
|
+
|
62
|
+
hash.one.should == "one"
|
63
|
+
hash.two.should == "two"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/watch.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# A simple alternative to autotest that isnt as painful
|
2
|
+
|
3
|
+
options = {
|
4
|
+
:options => "--require 'spec/spec_helper' --format nested --color",
|
5
|
+
:binary => "spec"
|
6
|
+
}
|
7
|
+
|
8
|
+
watch("(lib|spec)/(.*)\.rb") do |match|
|
9
|
+
puts %x[ clear ]
|
10
|
+
|
11
|
+
file = match[match.size - 1]
|
12
|
+
opts = options[:options]
|
13
|
+
binary = options[:binary]
|
14
|
+
|
15
|
+
files = []
|
16
|
+
|
17
|
+
["spec/lib/*.rb", "spec/lib/*/*.rb"].each do |glob|
|
18
|
+
Dir.glob(glob).each { |f| files << f }
|
19
|
+
end
|
20
|
+
|
21
|
+
puts "Found:"
|
22
|
+
files.each { |f| puts "+ #{f}" }
|
23
|
+
puts ""
|
24
|
+
command = "#{binary} #{files.collect! { |f| File.expand_path(f) }.join(" ")} #{opts}"
|
25
|
+
|
26
|
+
system(command)
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: configr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Josh Nesbitt
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-26 00:00:00 +00:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.9
|
24
|
+
version:
|
25
|
+
description: "Configr aims to provide a more Ruby-like interface to configuring and reading a set of configuration values. The idea evolved from using a standard hash as a configuration store into a more elegant way to declare and read values from within a hash. "
|
26
|
+
email: josh@josh-nesbitt.net
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- LICENSE
|
33
|
+
files:
|
34
|
+
- LICENSE
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- examples/all.rb
|
38
|
+
- lib/configr.rb
|
39
|
+
- lib/configr/configuration.rb
|
40
|
+
- lib/configr/configuration_block.rb
|
41
|
+
- lib/configr/errors.rb
|
42
|
+
- lib/configr/hash.rb
|
43
|
+
- readme.rdoc
|
44
|
+
- spec/fixtures/configuration.yml
|
45
|
+
- spec/lib/configuration_block_spec.rb
|
46
|
+
- spec/lib/configuration_spec.rb
|
47
|
+
- spec/lib/errors_spec.rb
|
48
|
+
- spec/lib/hash_spec.rb
|
49
|
+
- spec/spec_helper.rb
|
50
|
+
- spec/watch.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://github.com/joshnesbitt/configr
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --charset=UTF-8
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.3.5
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: A more Rubyish approach to creating and accessing configuration values.
|
79
|
+
test_files:
|
80
|
+
- spec/lib/configuration_block_spec.rb
|
81
|
+
- spec/lib/configuration_spec.rb
|
82
|
+
- spec/lib/errors_spec.rb
|
83
|
+
- spec/lib/hash_spec.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
- spec/watch.rb
|
86
|
+
- examples/all.rb
|