brendan-simpleconfig 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +16 -0
- data/README +0 -0
- data/Rakefile +126 -0
- data/lib/simpleconfig.rb +104 -0
- data/spec/fixtures/folder1/data.yml +4 -0
- data/spec/fixtures/folder1/erbified.yml +1 -0
- data/spec/fixtures/folder1/other_data.yml +1 -0
- data/spec/fixtures/folder2/data.yml +4 -0
- data/spec/fixtures/folder2/only_in_folder2.yml +1 -0
- data/spec/fixtures/folder2/other_data.yml +1 -0
- data/spec/simpleconfig_spec.rb +64 -0
- data/spec/spec_helper.rb +12 -0
- metadata +75 -0
data/Manifest.txt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
lib
|
2
|
+
lib/simpleconfig.rb
|
3
|
+
Rakefile
|
4
|
+
README
|
5
|
+
spec
|
6
|
+
spec/fixtures
|
7
|
+
spec/fixtures/folder1
|
8
|
+
spec/fixtures/folder1/data.yml
|
9
|
+
spec/fixtures/folder1/erbified.yml
|
10
|
+
spec/fixtures/folder1/other_data.yml
|
11
|
+
spec/fixtures/folder2
|
12
|
+
spec/fixtures/folder2/data.yml
|
13
|
+
spec/fixtures/folder2/only_in_folder2.yml
|
14
|
+
spec/fixtures/folder2/other_data.yml
|
15
|
+
spec/simpleconfig_spec.rb
|
16
|
+
spec/spec_helper.rb
|
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
|
3
|
+
require 'rubygems'
|
4
|
+
require './lib/simpleconfig.rb'
|
5
|
+
require 'rake'
|
6
|
+
require 'spec/rake/spectask'
|
7
|
+
|
8
|
+
desc "Generates the gemspec, Manifest.txt and builds the gem."
|
9
|
+
task :gem => ["gem:gemspec","gem:manifest"]
|
10
|
+
|
11
|
+
namespace :gem do
|
12
|
+
desc "Generates the simpleconfig.gemspec file"
|
13
|
+
task :gemspec do
|
14
|
+
gemspec_code = <<-gemspec
|
15
|
+
Gem::Specification.new do |s|
|
16
|
+
s.name = %q{simpleconfig}
|
17
|
+
s.version = #{SimpleConfig::VERSION.inspect}
|
18
|
+
|
19
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
20
|
+
|
21
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
22
|
+
s.authors = #{SimpleConfig::AUTHORS.inspect}
|
23
|
+
s.date = #{Time.now.strftime('%Y-%m-%d').inspect}
|
24
|
+
s.default_executable = nil
|
25
|
+
s.description = #{SimpleConfig::DESCRIPTION.inspect}
|
26
|
+
s.email = #{SimpleConfig::EMAIL.inspect}
|
27
|
+
s.executables = []
|
28
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
29
|
+
s.files = #{SimpleConfig::MANIFEST.inspect}
|
30
|
+
s.has_rdoc = true
|
31
|
+
s.homepage = #{SimpleConfig::HOMEPAGE.inspect}
|
32
|
+
s.rdoc_options = ["--main", "README.txt"]
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = %q{1.1.1}
|
35
|
+
s.summary = #{SimpleConfig::DESCRIPTION.inspect}
|
36
|
+
end
|
37
|
+
gemspec
|
38
|
+
gemspec = File.open(File.join(File.dirname(__FILE__),'simpleconfig.gemspec'),'w')
|
39
|
+
gemspec.write(gemspec_code)
|
40
|
+
gemspec.close
|
41
|
+
end
|
42
|
+
desc "Generates the Manifest.txt file"
|
43
|
+
task :manifest do
|
44
|
+
manifest = File.open(File.join(File.dirname(__FILE__),'Manifest.txt'),'w')
|
45
|
+
manifest.write(SimpleConfig::MANIFEST.join("\n")<<"\n")
|
46
|
+
manifest.close
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Run all specs"
|
51
|
+
Spec::Rake::SpecTask.new do |t|
|
52
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
53
|
+
end
|
54
|
+
|
55
|
+
namespace :spec do
|
56
|
+
desc "Run all specs and stake out all files/folders for changes, running rake spec upon change"
|
57
|
+
task :auto => 'spec' do
|
58
|
+
|
59
|
+
# This task assumes you are running on a Mac, with growl installed. Perhaps
|
60
|
+
# there will be a better way to abstract this, but it works for us now.
|
61
|
+
def growl(title, msg, img, pri=0, sticky="")
|
62
|
+
system "growlnotify -n autotest --image ~/.autotest_images/#{img} -p #{pri} -m #{msg.inspect} #{title} #{sticky}"
|
63
|
+
end
|
64
|
+
def self.growl_fail(output)
|
65
|
+
growl "FAIL", "#{output}", "fail.png", 2
|
66
|
+
end
|
67
|
+
def self.growl_pass(output)
|
68
|
+
growl "Pass", "#{output}", "pass.png"
|
69
|
+
end
|
70
|
+
|
71
|
+
command = 'rake spec'
|
72
|
+
files = {}
|
73
|
+
|
74
|
+
def files.reglob
|
75
|
+
Dir['**/*.rb'].each {|file| self[file] ||= File.mtime(file)}
|
76
|
+
end
|
77
|
+
|
78
|
+
files.reglob
|
79
|
+
|
80
|
+
puts "Watching #{files.keys.join(', ')}\n\nFiles: #{files.keys.length}"
|
81
|
+
|
82
|
+
trap('INT') do
|
83
|
+
puts "\nQuitting..."
|
84
|
+
exit
|
85
|
+
end
|
86
|
+
|
87
|
+
loop do
|
88
|
+
|
89
|
+
sleep 3
|
90
|
+
|
91
|
+
files.reglob
|
92
|
+
|
93
|
+
changed_file, last_changed = files.find do |file, last_changed|
|
94
|
+
begin
|
95
|
+
File.mtime(file) > last_changed
|
96
|
+
rescue
|
97
|
+
files.delete(file)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
if changed_file
|
102
|
+
files[changed_file] = File.mtime(changed_file)
|
103
|
+
puts "=> #{changed_file} changed, running #{command}"
|
104
|
+
results = `#{command}`
|
105
|
+
puts results
|
106
|
+
|
107
|
+
if results.include? 'tests'
|
108
|
+
output = results.slice(/(\d+)\s+tests?,\s*(\d+)\s+assertions?,\s*(\d+)\s+failures?(,\s*(\d+)\s+errors)?/)
|
109
|
+
if output
|
110
|
+
$~[3].to_i + $~[5].to_i > 0 ? growl_fail(output) : growl_pass(output)
|
111
|
+
end
|
112
|
+
else
|
113
|
+
output = results.slice(/(\d+)\s+examples?,\s*(\d+)\s+failures?(,\s*(\d+)\s+not implemented)?/)
|
114
|
+
if output
|
115
|
+
$~[2].to_i > 0 ? growl_fail(output) : growl_pass(output)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
# TODO Generic growl notification for other actions
|
119
|
+
|
120
|
+
puts "=> done"
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
data/lib/simpleconfig.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class SimpleConfig < Hash
|
5
|
+
|
6
|
+
VERSION='0.0.1'
|
7
|
+
AUTHORS=["Brendan Baldwin"]
|
8
|
+
EMAIL=["brendan@usergenic.com"]
|
9
|
+
DESCRIPTION=%q{This is a really simple system for getting configuration data into your app. See the wiki at http://github.com/brendan/simpleconfig/wikis for usage.}
|
10
|
+
FOLDER=File.expand_path(File.join(File.dirname(__FILE__),'..'))
|
11
|
+
MANIFEST=Dir.glob(File.join(FOLDER,'**','*')).map{|path|path[FOLDER.size+1..-1]}
|
12
|
+
HOMEPAGE="http://github.com/brendan/simpleconfig/wikis"
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
super key.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key,value)
|
19
|
+
value = self.class.new.replace(value) if value.is_a?(Hash) and !value.is_a?(self.class)
|
20
|
+
super key.to_s, value
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch(key, default=nil, &block)
|
24
|
+
super(key.to_s, default, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def freeze
|
28
|
+
values.each do |value|
|
29
|
+
value.freeze if value.respond_to?(:freeze)
|
30
|
+
end
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def has_key?(key)
|
35
|
+
super key.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def key?(key)
|
39
|
+
super key.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
def merge!(other)
|
43
|
+
other.each do |key, value|
|
44
|
+
if self[key].is_a?(Hash) and value.is_a?(Hash)
|
45
|
+
self[key].merge!(value)
|
46
|
+
else
|
47
|
+
self[key] = value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def replace(other)
|
53
|
+
clear
|
54
|
+
other.each do |key, value|
|
55
|
+
self[key] = value
|
56
|
+
end
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
|
62
|
+
def methodize_keys_and_freeze
|
63
|
+
keys.each do |key|
|
64
|
+
value = send(key)
|
65
|
+
value.methodize_keys_and_freeze if value.is_a?(Hash)
|
66
|
+
end
|
67
|
+
freeze
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def initialize(*folders)
|
74
|
+
@folders = folders unless folders.empty?
|
75
|
+
end
|
76
|
+
|
77
|
+
def load_and_merge(paths)
|
78
|
+
merged_data = nil
|
79
|
+
paths.each do |path|
|
80
|
+
if File.exists?(path)
|
81
|
+
data = YAML.load(ERB.new(File.read(path)).result)
|
82
|
+
data = self.class.new.replace(data) if data.is_a?(Hash)
|
83
|
+
if merged_data.is_a?(Hash)
|
84
|
+
merged_data.merge!(data)
|
85
|
+
else
|
86
|
+
merged_data = data
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
merged_data.methodize_keys_and_freeze if merged_data.is_a?(Hash)
|
91
|
+
merged_data
|
92
|
+
end
|
93
|
+
|
94
|
+
def method_missing(method_id, *arguments, &block)
|
95
|
+
if defined?(@folders)
|
96
|
+
data = load_and_merge(@folders.reverse.map {|f| File.join(f,"#{method_id}.yml")})
|
97
|
+
self[method_id] = data unless data == nil
|
98
|
+
end
|
99
|
+
return super unless key?(method_id)
|
100
|
+
class << self; self; end.send(:define_method, method_id) { self[method_id] }
|
101
|
+
send(method_id)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= %w{a dynamic key}.join('_') %> : some_<%='dynamic'%>_content
|
@@ -0,0 +1 @@
|
|
1
|
+
definitely_not_a_hash
|
@@ -0,0 +1 @@
|
|
1
|
+
i_am_so_uniq
|
@@ -0,0 +1 @@
|
|
1
|
+
not_a_hash
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe "SimpleConfig" do
|
4
|
+
|
5
|
+
def fixture_folders
|
6
|
+
%w{folder1 folder2}.map{|f|File.join(File.dirname(__FILE__),'fixtures',f)}
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".new" do
|
10
|
+
|
11
|
+
it "creates a new SimpleConfig hash and sets the @folders instance_variable to the list of arguments provided." do
|
12
|
+
config = SimpleConfig.new('x','y','z')
|
13
|
+
config.instance_variable_get('@folders').should == ['x','y','z']
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#method_missing" do
|
19
|
+
|
20
|
+
it "when a key matching the method_id string is present, defines a singleton_method named for the key to return the value and calls it." do
|
21
|
+
config = SimpleConfig.new
|
22
|
+
config['some_key']=1
|
23
|
+
config.should be_key('some_key')
|
24
|
+
config.methods.should_not include('some_key')
|
25
|
+
config.some_key.should == 1
|
26
|
+
config.methods.should include('some_key')
|
27
|
+
config.some_key.should == 1
|
28
|
+
end
|
29
|
+
|
30
|
+
it "delegates to method_missing super if no matching key is found" do
|
31
|
+
config = SimpleConfig.new
|
32
|
+
config[:this_method_does_exist] = "good_for_you"
|
33
|
+
proc{config.this_method_does_not_exist}.should raise_error(NoMethodError)
|
34
|
+
proc{config.this_method_does_exist}.should_not raise_error(NoMethodError)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "when all is said and done" do
|
40
|
+
|
41
|
+
it "performs a load_and_merge for all files named data.yml in specified folders, giving preference to first" do
|
42
|
+
config = SimpleConfig.new(*fixture_folders)
|
43
|
+
config.data.some_key.should == 'some_value'
|
44
|
+
config.data.some_other_key.should == 'some_other_value'
|
45
|
+
config.data.some_key_with_hash_value.some_subkey.should == 'some_subvalue'
|
46
|
+
config.data.some_key_with_hash_value.some_other_subkey.should == 'some_other_subvalue'
|
47
|
+
config.should == {
|
48
|
+
'data' => {
|
49
|
+
'some_key' => 'some_value',
|
50
|
+
'some_other_key' => 'some_other_value',
|
51
|
+
'some_key_with_hash_value' => {
|
52
|
+
'some_subkey' => 'some_subvalue',
|
53
|
+
'some_other_subkey' => 'some_other_subvalue' }}}
|
54
|
+
end
|
55
|
+
|
56
|
+
it "runs file content through ERB before parsing with YAML" do
|
57
|
+
config = SimpleConfig.new(*fixture_folders)
|
58
|
+
config.erbified.a_dynamic_key.should == 'some_dynamic_content'
|
59
|
+
config.should == {'erbified' => {'a_dynamic_key' => 'some_dynamic_content'}}
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: brendan-simpleconfig
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brendan Baldwin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-07-02 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: This is a really simple system for getting configuration data into your app. See the wiki at http://github.com/brendan/simpleconfig/wikis for usage.
|
17
|
+
email:
|
18
|
+
- brendan@usergenic.com
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files:
|
24
|
+
- History.txt
|
25
|
+
- Manifest.txt
|
26
|
+
- README.txt
|
27
|
+
files:
|
28
|
+
- lib
|
29
|
+
- lib/simpleconfig.rb
|
30
|
+
- Rakefile
|
31
|
+
- README
|
32
|
+
- spec
|
33
|
+
- spec/fixtures
|
34
|
+
- spec/fixtures/folder1
|
35
|
+
- spec/fixtures/folder1/data.yml
|
36
|
+
- spec/fixtures/folder1/erbified.yml
|
37
|
+
- spec/fixtures/folder1/other_data.yml
|
38
|
+
- spec/fixtures/folder2
|
39
|
+
- spec/fixtures/folder2/data.yml
|
40
|
+
- spec/fixtures/folder2/only_in_folder2.yml
|
41
|
+
- spec/fixtures/folder2/other_data.yml
|
42
|
+
- spec/simpleconfig_spec.rb
|
43
|
+
- spec/spec_helper.rb
|
44
|
+
- History.txt
|
45
|
+
- Manifest.txt
|
46
|
+
- README.txt
|
47
|
+
has_rdoc: true
|
48
|
+
homepage: http://github.com/brendan/simpleconfig/wikis
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options:
|
51
|
+
- --main
|
52
|
+
- README.txt
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.2.0
|
71
|
+
signing_key:
|
72
|
+
specification_version: 2
|
73
|
+
summary: This is a really simple system for getting configuration data into your app. See the wiki at http://github.com/brendan/simpleconfig/wikis for usage.
|
74
|
+
test_files: []
|
75
|
+
|