configuratron 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.travis.yml +6 -0
- data/Gemfile +11 -0
- data/Guardfile +8 -0
- data/Rakefile +8 -0
- data/configuratron.gemspec +21 -0
- data/lib/configuratron.rb +76 -0
- data/lib/configuratron/blank_slate.rb +75 -0
- data/spec/configuratron/config_hash_spec.rb +93 -0
- data/spec/configuratron/configurable_spec.rb +41 -0
- data/spec/configuratron/configuratron_spec.rb +29 -0
- data/spec/spec_helper.rb +7 -0
- metadata +106 -0
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2, :cli => "--color --format nested", :rvm => ['1.8.7', '1.9.2'] do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { "spec" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "configuratron"
|
5
|
+
s.version = "0.0.1"
|
6
|
+
s.authors = ["Grzesiek Kolodziejczyk"]
|
7
|
+
s.email = ["gkolodziejczyk@gmail.com"]
|
8
|
+
s.homepage = "https://github.com/grk/configuratron"
|
9
|
+
s.summary = %q{Configuration storage library}
|
10
|
+
s.description = %q{Configuration storage library for Ruby with metaprogramming magic. Allows for hash-like and method-based key access.}
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec", ">= 2.6.0"
|
18
|
+
s.add_development_dependency "guard-rspec"
|
19
|
+
s.add_development_dependency "rake", ">= 0.9.2"
|
20
|
+
s.add_development_dependency "bundler"
|
21
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "configuratron/blank_slate"
|
2
|
+
|
3
|
+
class Configuratron < BlankSlate
|
4
|
+
def initialize
|
5
|
+
@config = ConfigHash.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def [](key)
|
9
|
+
@config[key]
|
10
|
+
end
|
11
|
+
|
12
|
+
def []=(key, value)
|
13
|
+
@config[key] = value
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(name, *args, &block)
|
17
|
+
@config.__send__(name, *args, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
module Configurable
|
21
|
+
def config
|
22
|
+
@config ||= Configuratron.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class ConfigHash < BlankSlate
|
27
|
+
def initialize(hash = nil)
|
28
|
+
@hash = {}
|
29
|
+
if hash
|
30
|
+
hash.each do |k,v|
|
31
|
+
@hash[k] = v.is_a?(Hash) ? ConfigHash.new(v) : v
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def []=(k, v)
|
37
|
+
@hash[k] = v.is_a?(Hash) ? ConfigHash.new(v) : v
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](k)
|
41
|
+
@hash[k]
|
42
|
+
end
|
43
|
+
|
44
|
+
def method_missing(name, *args, &block)
|
45
|
+
if name.to_s[-1..-1] == '=' # workaround for 1.8 returning char
|
46
|
+
base_name = name.to_s[0..-2].to_sym
|
47
|
+
_define_singleton_method(name) do |name|
|
48
|
+
__send__ :[]=, base_name, value
|
49
|
+
end
|
50
|
+
__send__ :[]=, base_name, *args
|
51
|
+
else
|
52
|
+
_define_singleton_method(name) do
|
53
|
+
__send__ :[], name.to_sym
|
54
|
+
end
|
55
|
+
__send__ :[], name.to_sym
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def _singleton_class
|
61
|
+
class << self
|
62
|
+
self
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def _singleton_exec(*args, &block)
|
67
|
+
_singleton_class.instance_exec(*args, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
def _define_singleton_method(name, &block)
|
71
|
+
_singleton_exec(name) do |name|
|
72
|
+
define_method(name, &block)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class BlankSlate
|
2
|
+
class << self
|
3
|
+
|
4
|
+
# Hide the method named +name+ in the BlankSlate class. Don't
|
5
|
+
# hide +instance_eval+ or any method beginning with "__".
|
6
|
+
def hide(name)
|
7
|
+
if instance_methods.include?(name) and name.to_s !~ /^(__|instance_eval|object_id)/
|
8
|
+
@hidden_methods ||= {}
|
9
|
+
@hidden_methods[name] = instance_method(name)
|
10
|
+
undef_method name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_hidden_method(name)
|
15
|
+
@hidden_methods ||= {}
|
16
|
+
@hidden_methods[name] || (superclass.find_hidden_method(name) if superclass.respond_to?(:find_hidden_method))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Redefine a previously hidden method so that it may be called on a blank
|
20
|
+
# slate object.
|
21
|
+
def reveal(name)
|
22
|
+
unbound_method = find_hidden_method(name)
|
23
|
+
fail "Don't know how to reveal method '#{name}'" unless unbound_method
|
24
|
+
define_method(name, unbound_method)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
instance_methods.each { |m| hide(m) }
|
29
|
+
end
|
30
|
+
|
31
|
+
module Kernel
|
32
|
+
class << self
|
33
|
+
alias_method :blank_slate_method_added, :method_added
|
34
|
+
|
35
|
+
# Detect method additions to Kernel and remove them in the
|
36
|
+
# BlankSlate class.
|
37
|
+
def method_added(name)
|
38
|
+
result = blank_slate_method_added(name)
|
39
|
+
return result if self != Kernel
|
40
|
+
BlankSlate.hide(name)
|
41
|
+
result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Object
|
47
|
+
class << self
|
48
|
+
alias_method :blank_slate_method_added, :method_added
|
49
|
+
|
50
|
+
# Detect method additions to Object and remove them in the
|
51
|
+
# BlankSlate class.
|
52
|
+
def method_added(name)
|
53
|
+
result = blank_slate_method_added(name)
|
54
|
+
return result if self != Object
|
55
|
+
BlankSlate.hide(name)
|
56
|
+
result
|
57
|
+
end
|
58
|
+
|
59
|
+
def find_hidden_method(name)
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Module
|
66
|
+
alias blankslate_original_append_features append_features
|
67
|
+
def append_features(mod)
|
68
|
+
result = blankslate_original_append_features(mod)
|
69
|
+
return result if mod != Object
|
70
|
+
instance_methods.each do |name|
|
71
|
+
BlankSlate.hide(name)
|
72
|
+
end
|
73
|
+
result
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Configuratron::ConfigHash do
|
4
|
+
%w(instance_variable_get is_a? methods).each do |m|
|
5
|
+
if RUBY18
|
6
|
+
Configuratron::ConfigHash.reveal(m)
|
7
|
+
else
|
8
|
+
Configuratron::ConfigHash.reveal(m.to_sym)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
|
13
|
+
Configuratron::ConfigHash.reveal("singleton_methods")
|
14
|
+
Configuratron::ConfigHash.reveal("kind_of?")
|
15
|
+
end
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
@ch = Configuratron::ConfigHash.new
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when created" do
|
22
|
+
it "should be empty" do
|
23
|
+
@ch.instance_variable_get(:@hash).should be_empty
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "keys" do
|
28
|
+
it "should return nil for missing key" do
|
29
|
+
@ch[:missing_key].should be_nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should set value for new key" do
|
33
|
+
@ch[:new_key] = :value
|
34
|
+
@ch.instance_variable_get(:@hash)[:new_key].should eql(:value)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return value for existing key" do
|
38
|
+
@ch.instance_variable_get(:@hash)[:existing_key] = :value
|
39
|
+
@ch[:existing_key].should eql(:value)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "method access" do
|
44
|
+
it "should return nil for missing key" do
|
45
|
+
@ch.missing_key.should be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should set value for new key" do
|
49
|
+
@ch.new_key = :value
|
50
|
+
@ch.instance_variable_get(:@hash)[:new_key].should eql(:value)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should return value for existing key" do
|
54
|
+
@ch.instance_variable_get(:@hash)[:existing_key] = :value
|
55
|
+
@ch.existing_key.should eql(:value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "hash keys" do
|
60
|
+
it "should convert hash keys to self class" do
|
61
|
+
@ch[:hash_key] = {:new => :hash}
|
62
|
+
@ch[:hash_key].should be_a(Configuratron::ConfigHash)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should convert nested hash keys recursively" do
|
66
|
+
@ch[:nested_hash] = {:root => {:nested => :value}}
|
67
|
+
@ch[:nested_hash].should be_a(Configuratron::ConfigHash)
|
68
|
+
@ch[:nested_hash][:root].should be_a(Configuratron::ConfigHash)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should access nested hash keys by methods" do
|
72
|
+
@ch.nested_hash = {:root => {:nested => :value}}
|
73
|
+
@ch.nested_hash.should be_a(Configuratron::ConfigHash)
|
74
|
+
@ch.nested_hash.root.should be_a(Configuratron::ConfigHash)
|
75
|
+
@ch.nested_hash.root.nested.should eql(:value)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "defining methods on method_missing" do
|
80
|
+
it "should not have instance methods defined before first call" do
|
81
|
+
@ch.methods.should_not include(RUBY18 ? "test_key" : :test_key)
|
82
|
+
@ch.methods.should_not include(RUBY18 ? "test_key=" : :test_key=)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should have instance methods defined after first call" do
|
86
|
+
@ch.test_key
|
87
|
+
@ch.methods.should include(RUBY18 ? "test_key" : :test_key)
|
88
|
+
|
89
|
+
@ch.test_key = :value
|
90
|
+
@ch.methods.should include(RUBY18 ? "test_key=" : :test_key=)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Configuratron::Configurable do
|
4
|
+
context "included" do
|
5
|
+
class A
|
6
|
+
include Configuratron::Configurable
|
7
|
+
end
|
8
|
+
|
9
|
+
before(:all) do
|
10
|
+
@a = A.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should define config for instances" do
|
14
|
+
@a.should respond_to(:config)
|
15
|
+
@a.config.should be_a(Configuratron)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should not define config for class" do
|
19
|
+
A.should_not respond_to(:config)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "extended" do
|
24
|
+
class B
|
25
|
+
extend Configuratron::Configurable
|
26
|
+
end
|
27
|
+
|
28
|
+
before(:all) do
|
29
|
+
@b = B.new
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not define config for instances" do
|
33
|
+
@b.should_not respond_to(:config)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should define config for class" do
|
37
|
+
B.should respond_to(:config)
|
38
|
+
B.config.should be_a(Configuratron)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Configuratron do
|
4
|
+
before(:each) do
|
5
|
+
@c = Configuratron.new
|
6
|
+
end
|
7
|
+
|
8
|
+
context "hash-like access" do
|
9
|
+
it "should return nil for missing keys" do
|
10
|
+
@c[:key].should be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should set value for new keys" do
|
14
|
+
@c[:key] = :value
|
15
|
+
@c[:key].should eql(:value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "method access" do
|
20
|
+
it "should return nil for missing keys" do
|
21
|
+
@c.key.should be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set value for new keys" do
|
25
|
+
@c.key = :value
|
26
|
+
@c.key.should eql(:value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: configuratron
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Grzesiek Kolodziejczyk
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-06-11 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &2156046840 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.6.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2156046840
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: guard-rspec
|
27
|
+
requirement: &2156045780 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2156045780
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &2156044960 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.9.2
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2156044960
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bundler
|
49
|
+
requirement: &2156044360 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2156044360
|
58
|
+
description: Configuration storage library for Ruby with metaprogramming magic. Allows
|
59
|
+
for hash-like and method-based key access.
|
60
|
+
email:
|
61
|
+
- gkolodziejczyk@gmail.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- .travis.yml
|
68
|
+
- Gemfile
|
69
|
+
- Guardfile
|
70
|
+
- Rakefile
|
71
|
+
- configuratron.gemspec
|
72
|
+
- lib/configuratron.rb
|
73
|
+
- lib/configuratron/blank_slate.rb
|
74
|
+
- spec/configuratron/config_hash_spec.rb
|
75
|
+
- spec/configuratron/configurable_spec.rb
|
76
|
+
- spec/configuratron/configuratron_spec.rb
|
77
|
+
- spec/spec_helper.rb
|
78
|
+
homepage: https://github.com/grk/configuratron
|
79
|
+
licenses: []
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.8.5
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Configuration storage library
|
102
|
+
test_files:
|
103
|
+
- spec/configuratron/config_hash_spec.rb
|
104
|
+
- spec/configuratron/configurable_spec.rb
|
105
|
+
- spec/configuratron/configuratron_spec.rb
|
106
|
+
- spec/spec_helper.rb
|