configatron 4.1.0 → 4.1.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/History.txt +4 -0
- data/README.md +2 -2
- data/lib/configatron/deep_clone.rb +14 -12
- data/lib/configatron/root_store.rb +1 -2
- data/lib/configatron/store.rb +20 -23
- data/lib/configatron/version.rb +1 -1
- data/lib/generators/configatron/install/templates/configatron/defaults.rb +2 -2
- data/lib/generators/configatron/install/templates/configatron/development.rb +2 -2
- data/lib/generators/configatron/install/templates/configatron/production.rb +2 -2
- data/lib/generators/configatron/install/templates/configatron/test.rb +2 -2
- data/lib/generators/configatron/install/templates/initializers/configatron.rb +0 -2
- data/test/functional/configatron.rb +7 -3
- data/test/functional/delayed.rb +18 -0
- metadata +6 -4
data/History.txt
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
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!
|
5
5
|
|
6
|
-
One of the more important changes to V3 is that it now resembles more a `Hash` style interface. You can use `[]`, `fetch`, `each`, etc... Actually the hash notation is more robust since the dot notation won't work for
|
6
|
+
One of the more important changes to V3 is that it now resembles more a `Hash` style interface. You can use `[]`, `fetch`, `each`, etc... Actually the hash notation is a bit more robust since the dot notation won't work for a few property names (a few public methods from `Configatron::Store` itself).
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
@@ -78,7 +78,7 @@ configatron.email.pop.port # => 110
|
|
78
78
|
|
79
79
|
### Method vs hash access
|
80
80
|
|
81
|
-
As a note, method (`configatron.foo`) access will be shadowed by public methods defined on the configatron object. (The configatron object descends from [`BasicObject`](http://apidock.com/ruby/BasicObject) and
|
81
|
+
As a note, method (`configatron.foo`) access will be shadowed by public methods defined on the configatron object. (The configatron object descends from [`BasicObject`](http://apidock.com/ruby/BasicObject) and adds a few methods to resemble the `Hash` API and to play nice with `puts`, so it should have a pretty bare set of methods.)
|
82
82
|
|
83
83
|
If you need to use keys that are themselves method names, you can just use hash access (`configatron['foo']`).
|
84
84
|
|
@@ -35,30 +35,32 @@ module Configatron::DeepClone
|
|
35
35
|
# You can redistribute it and/or modify it under the same terms of Ruby's license;
|
36
36
|
# either the dual license version in 2003, or any later version.
|
37
37
|
def self.deep_clone( obj=self, cloned={} )
|
38
|
-
if
|
38
|
+
if Configatron::RootStore === obj
|
39
39
|
# We never actually want to have multiple copies of our
|
40
40
|
# Configatron::RootStore (and every Store has a reference).
|
41
41
|
return obj
|
42
|
-
elsif cloned.
|
43
|
-
return cloned[obj.
|
42
|
+
elsif cloned.key?( obj.__id__ )
|
43
|
+
return cloned[obj.__id__]
|
44
44
|
else
|
45
45
|
begin
|
46
46
|
cl = obj.clone
|
47
47
|
rescue Exception
|
48
48
|
# unclonnable (TrueClass, Fixnum, ...)
|
49
|
-
cloned[obj.
|
49
|
+
cloned[obj.__id__] = obj
|
50
50
|
return obj
|
51
51
|
else
|
52
|
-
cloned[obj.
|
53
|
-
cloned[cl.
|
54
|
-
|
55
|
-
|
52
|
+
cloned[obj.__id__] = cl
|
53
|
+
cloned[cl.__id__] = cl
|
54
|
+
case
|
55
|
+
when Configatron::Store === cl then return cl
|
56
|
+
when Hash === cl
|
57
|
+
cl.clone.each do |k,v|
|
56
58
|
cl[k] = deep_clone( v, cloned )
|
57
|
-
|
58
|
-
|
59
|
-
cl.collect!
|
59
|
+
end
|
60
|
+
when Array === cl
|
61
|
+
cl.collect! do |v|
|
60
62
|
deep_clone( v, cloned )
|
61
|
-
|
63
|
+
end
|
62
64
|
end
|
63
65
|
cl.instance_variables.each do |var|
|
64
66
|
v = cl.instance_eval( var.to_s )
|
@@ -3,7 +3,6 @@ require 'singleton'
|
|
3
3
|
# This is the root configatron object, and contains methods which
|
4
4
|
# operate on the entire configatron hierarchy.
|
5
5
|
class Configatron::RootStore < BasicObject
|
6
|
-
include ::Kernel
|
7
6
|
include ::Singleton
|
8
7
|
extend ::Forwardable
|
9
8
|
|
@@ -21,7 +20,7 @@ class Configatron::RootStore < BasicObject
|
|
21
20
|
end
|
22
21
|
|
23
22
|
def method_missing(name, *args, &block)
|
24
|
-
store.
|
23
|
+
store.__send__(name, *args, &block)
|
25
24
|
end
|
26
25
|
|
27
26
|
def reset!
|
data/lib/configatron/store.rb
CHANGED
@@ -2,7 +2,6 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
class Configatron
|
4
4
|
class Store < BasicObject
|
5
|
-
include ::Kernel
|
6
5
|
extend ::Forwardable
|
7
6
|
|
8
7
|
def initialize(root_store, name='configatron', attributes={})
|
@@ -14,7 +13,7 @@ class Configatron
|
|
14
13
|
def [](key)
|
15
14
|
val = fetch(key.to_sym) do
|
16
15
|
if @root_store.locked?
|
17
|
-
raise ::Configatron::UndefinedKeyError.new("Key not found: #{key} (for locked #{self})")
|
16
|
+
::Kernel.raise ::Configatron::UndefinedKeyError.new("Key not found: #{key} (for locked #{self})")
|
18
17
|
end
|
19
18
|
::Configatron::Store.new(@root_store, "#{@name}.#{key}")
|
20
19
|
end
|
@@ -23,22 +22,22 @@ class Configatron
|
|
23
22
|
|
24
23
|
def store(key, value)
|
25
24
|
if @root_store.locked?
|
26
|
-
raise ::Configatron::LockedError.new("Cannot set key #{key} for locked #{self}")
|
25
|
+
::Kernel.raise ::Configatron::LockedError.new("Cannot set key #{key} for locked #{self}")
|
27
26
|
end
|
28
27
|
@attributes[key.to_sym] = value
|
29
28
|
end
|
30
29
|
|
31
30
|
def fetch(key, default_value = nil, &block)
|
32
31
|
val = @attributes[key.to_sym]
|
33
|
-
if val
|
34
|
-
if
|
32
|
+
if val == nil
|
33
|
+
if block
|
35
34
|
val = block.call
|
36
35
|
elsif default_value
|
37
36
|
val = default_value
|
38
37
|
end
|
39
38
|
store(key, val)
|
40
39
|
end
|
41
|
-
if
|
40
|
+
if ::Configatron::Proc === val
|
42
41
|
val = val.call
|
43
42
|
end
|
44
43
|
return val
|
@@ -50,7 +49,7 @@ class Configatron
|
|
50
49
|
|
51
50
|
def configure_from_hash(hash)
|
52
51
|
hash.each do |key, value|
|
53
|
-
if
|
52
|
+
if ::Hash === value
|
54
53
|
self[key].configure_from_hash(value)
|
55
54
|
else
|
56
55
|
store(key, value)
|
@@ -65,7 +64,7 @@ class Configatron
|
|
65
64
|
def inspect
|
66
65
|
f_out = []
|
67
66
|
@attributes.each do |k, v|
|
68
|
-
if
|
67
|
+
if ::Configatron::Store === v
|
69
68
|
v.inspect.each_line do |line|
|
70
69
|
if line.match(/\n/)
|
71
70
|
line.each_line do |l|
|
@@ -85,25 +84,23 @@ class Configatron
|
|
85
84
|
end
|
86
85
|
|
87
86
|
def method_missing(name, *args, &block)
|
88
|
-
# Needed to allow 'puts'ing of a configatron.
|
89
|
-
if name == :to_ary
|
90
|
-
raise ::NoMethodError.new("Called :to_ary")
|
91
|
-
end
|
92
|
-
|
93
|
-
# In case of Configatron bugs, prevent method_missing infinite
|
94
|
-
# loops.
|
95
|
-
if @method_missing
|
96
|
-
raise ::NoMethodError.new("Bug in configatron; ended up in method_missing while running: #{name.inspect}")
|
97
|
-
end
|
98
|
-
@method_missing = true
|
99
87
|
do_lookup(name, *args, &block)
|
100
|
-
ensure
|
101
|
-
@method_missing = false
|
102
88
|
end
|
103
89
|
|
104
90
|
# Needed for deep_clone to actually clone this object
|
105
91
|
def clone
|
106
|
-
|
92
|
+
Store.new(@root_store, @name, @attributes.clone)
|
93
|
+
end
|
94
|
+
|
95
|
+
# So that puts works (it expects the object to respond to to_ary)
|
96
|
+
def to_ary
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
# So that we keep backward-compatibility in case people are using nil? to check
|
101
|
+
# configatron settings:
|
102
|
+
def nil?
|
103
|
+
false
|
107
104
|
end
|
108
105
|
|
109
106
|
private
|
@@ -120,7 +117,7 @@ class Configatron
|
|
120
117
|
if self.has_key?(key)
|
121
118
|
return self[key]
|
122
119
|
else
|
123
|
-
raise ::Configatron::UndefinedKeyError.new($1)
|
120
|
+
::Kernel.raise ::Configatron::UndefinedKeyError.new($1)
|
124
121
|
end
|
125
122
|
else
|
126
123
|
return self[name]
|
data/lib/configatron/version.rb
CHANGED
@@ -51,15 +51,19 @@ class Critic::Functional::ConfigatronTest < Critic::Functional::Test
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'raises an error when accessing non-existing values' do
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
assert @kernel.a != nil
|
55
|
+
assert @kernel.a.b != nil
|
56
|
+
assert @kernel.a.b.c != nil
|
57
57
|
assert_equal('DD', @kernel.a.b.c.d)
|
58
58
|
assert_raises(Configatron::UndefinedKeyError) do
|
59
59
|
@kernel.unknown
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
it 'responds to nil? for backward compatibility' do
|
64
|
+
refute_nil @kernel.a
|
65
|
+
end
|
66
|
+
|
63
67
|
it 'raises an error when trying to set a non-existing key' do
|
64
68
|
assert_raises(Configatron::LockedError) do
|
65
69
|
@kernel.unknown = 'known'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '_lib'
|
2
|
+
|
3
|
+
class Critic::Functional::DelayedTest < Critic::Functional::Test
|
4
|
+
before do
|
5
|
+
@kernel = Configatron::RootStore.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'delayed' do
|
9
|
+
before do
|
10
|
+
@kernel.a = Configatron::Delayed.new { @kernel.b }
|
11
|
+
@kernel.b = "expected"
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'works independent of the order' do
|
15
|
+
assert_equal('expected', @kernel.a)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: configatron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-06-
|
12
|
+
date: 2014-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -116,6 +116,7 @@ files:
|
|
116
116
|
- test/functional/_lib.rb
|
117
117
|
- test/functional/_lib/scripts/core.rb
|
118
118
|
- test/functional/configatron.rb
|
119
|
+
- test/functional/delayed.rb
|
119
120
|
- test/functional/loading.rb
|
120
121
|
- test/functional/minitest.rb
|
121
122
|
- test/unit/_lib.rb
|
@@ -137,7 +138,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
137
138
|
version: '0'
|
138
139
|
segments:
|
139
140
|
- 0
|
140
|
-
hash:
|
141
|
+
hash: 2777108850332874749
|
141
142
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
143
|
none: false
|
143
144
|
requirements:
|
@@ -146,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
147
|
version: '0'
|
147
148
|
segments:
|
148
149
|
- 0
|
149
|
-
hash:
|
150
|
+
hash: 2777108850332874749
|
150
151
|
requirements: []
|
151
152
|
rubyforge_project:
|
152
153
|
rubygems_version: 1.8.25
|
@@ -158,6 +159,7 @@ test_files:
|
|
158
159
|
- test/functional/_lib.rb
|
159
160
|
- test/functional/_lib/scripts/core.rb
|
160
161
|
- test/functional/configatron.rb
|
162
|
+
- test/functional/delayed.rb
|
161
163
|
- test/functional/loading.rb
|
162
164
|
- test/functional/minitest.rb
|
163
165
|
- test/unit/_lib.rb
|