brendan-simpleconfig 0.0.1
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/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
|
+
|