adhearsion-loquacious 1.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/Guardfile +5 -0
- data/History.txt +127 -0
- data/README.rdoc +229 -0
- data/Rakefile +30 -0
- data/adhearsion-loquacious.gemspec +32 -0
- data/examples/gutters.rb +29 -0
- data/examples/nested.rb +43 -0
- data/examples/simple.rb +20 -0
- data/lib/loquacious.rb +165 -0
- data/lib/loquacious/configuration.rb +406 -0
- data/lib/loquacious/configuration/help.rb +249 -0
- data/lib/loquacious/configuration/iterator.rb +158 -0
- data/lib/loquacious/core_ext/string.rb +75 -0
- data/lib/loquacious/undefined.rb +92 -0
- data/lib/loquacious/utility.rb +14 -0
- data/loquacious.gemspec +32 -0
- data/spec/configuration_spec.rb +513 -0
- data/spec/help_spec.rb +369 -0
- data/spec/iterator_spec.rb +70 -0
- data/spec/loquacious_spec.rb +76 -0
- data/spec/spec_helper.rb +70 -0
- data/spec/string_spec.rb +53 -0
- data/spec/utility_spec.rb +28 -0
- data/version.txt +1 -0
- metadata +102 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
module Loquacious
|
3
|
+
|
4
|
+
# Represents an undefined configuration value. An undefined value is
|
5
|
+
# assigned to each configuration propery by default. Any method can be
|
6
|
+
# invoked on an undefined value, and a warning message will be printed to
|
7
|
+
# the IO stream (defaulting to $stderr).
|
8
|
+
#
|
9
|
+
# The purpose of this class is to provide the user with a helpful message
|
10
|
+
# that the configuration values they are trying to use have not been setup
|
11
|
+
# correctly.
|
12
|
+
#
|
13
|
+
class Undefined
|
14
|
+
|
15
|
+
instance_methods(true).each do |m|
|
16
|
+
next if m[::Loquacious::KEEPERS]
|
17
|
+
undef_method m
|
18
|
+
end
|
19
|
+
private_instance_methods(true).each do |m|
|
20
|
+
next if m[::Loquacious::KEEPERS]
|
21
|
+
undef_method m
|
22
|
+
end
|
23
|
+
Kernel.methods.each do |m|
|
24
|
+
next if m[::Loquacious::KEEPERS]
|
25
|
+
module_eval <<-CODE
|
26
|
+
def #{m}( *args, &block )
|
27
|
+
self.method_missing('#{m}', *args, &block)
|
28
|
+
end
|
29
|
+
CODE
|
30
|
+
end
|
31
|
+
undef_method :method_missing rescue nil
|
32
|
+
|
33
|
+
@io = $stderr
|
34
|
+
@first_time = true
|
35
|
+
|
36
|
+
class << self
|
37
|
+
attr_accessor :io
|
38
|
+
|
39
|
+
# Write a warning message to the Undefined class IO stream. By default,
|
40
|
+
# this IO stream is set to the Ruby $stderr output.
|
41
|
+
#
|
42
|
+
def warn( key )
|
43
|
+
if @first_time
|
44
|
+
@io.puts <<-__
|
45
|
+
---------------------------------------------------------------------------
|
46
|
+
The Loquacious configuration system has detected that one or moe
|
47
|
+
settings have an undefined value. An attempt is being made to reference
|
48
|
+
sub-properties of these undefined settings. Messages will follow containing
|
49
|
+
information about the undefined properties.
|
50
|
+
---------------------------------------------------------------------------
|
51
|
+
__
|
52
|
+
@first_time = false
|
53
|
+
end
|
54
|
+
|
55
|
+
@io.puts "Access to undefined value #{key.first.inspect}: #{key.join('.')}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Creates a new undefined value returned from the lookup _key_ in some
|
60
|
+
# configuration object. The _key_ is used to alert the user where the
|
61
|
+
# undefined value came from.
|
62
|
+
#
|
63
|
+
def initialize( key )
|
64
|
+
@key = Kernel.Array(key)
|
65
|
+
end
|
66
|
+
|
67
|
+
# An undefined value acts like a +nil+ in that it has no value of its own.
|
68
|
+
# This method always returns +true+.
|
69
|
+
#
|
70
|
+
def nil?() true; end
|
71
|
+
|
72
|
+
# We can respond to any method except :call. The call method is reserved
|
73
|
+
# for Procs and lambdas, and it is used internally by loquacious for lazy
|
74
|
+
# evaluation of configuration parameters.
|
75
|
+
#
|
76
|
+
def respond_to_missing?( id, priv = false ) id != :call; end
|
77
|
+
|
78
|
+
# For every method invoked on an undefined object, generate a warning
|
79
|
+
# message describing the undefined value and the method that was called.
|
80
|
+
#
|
81
|
+
# Returns a new undefined object with the most recent method included in
|
82
|
+
# the key name.
|
83
|
+
#
|
84
|
+
def method_missing( method, *args, &block )
|
85
|
+
key = @key.dup << method.to_s
|
86
|
+
Undefined.warn key
|
87
|
+
return Undefined.new(key)
|
88
|
+
end
|
89
|
+
|
90
|
+
end # class Undefined
|
91
|
+
end # module Loquacious
|
92
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Loquacious
|
2
|
+
class Utility
|
3
|
+
class << self
|
4
|
+
# Returns the variable name to use for a value to be picked from ENV
|
5
|
+
#
|
6
|
+
def env_var_name(name, config)
|
7
|
+
parent_list = config.parent_list
|
8
|
+
parent_part = parent_list.empty? ? nil : parent_list.join("_")
|
9
|
+
key_name = name.to_s.split(".").last
|
10
|
+
[::Loquacious.env_prefix, parent_part, config.__name, key_name].compact.join("_").upcase
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/loquacious.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "loquacious"
|
5
|
+
s.version = "1.9.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Tim Pease"]
|
9
|
+
s.date = "2012-01-16"
|
10
|
+
s.description = "Descriptive configuration files for Ruby written in Ruby.\n\nLoquacious provides a very open configuration system written in ruby and\ndescriptions for each configuration attribute. The attributes and descriptions\ncan be iterated over allowing for helpful information about those attributes to\nbe displayed to the user.\n\nIn the simple case we have a file something like\n\n Loquacious.configuration_for('app') {\n name 'value', :desc => \"Defines the name\"\n foo 'bar', :desc => \"FooBar\"\n id 42, :desc => \"Ara T. Howard\"\n }\n\nWhich can be loaded via the standard Ruby loading mechanisms\n\n Kernel.load 'config/app.rb'\n\nThe attributes and their descriptions can be printed by using a Help object\n\n help = Loquacious.help_for('app')\n help.show :values => true # show the values for the attributes, too\n\nDescriptions are optional, and configurations can be nested arbitrarily deep.\n\n Loquacious.configuration_for('nested') {\n desc \"The outermost level\"\n a {\n desc \"One more level in\"\n b {\n desc \"Finally, a real value\"\n c 'value'\n }\n }\n }\n\n config = Loquacious.configuration_for('nested')\n\n p config.a.b.c #=> \"value\"\n\nAnd as you can see, descriptions can either be given inline after the value or\nthey can appear above the attribute and value on their own line."
|
11
|
+
s.email = "tim.pease@gmail.com"
|
12
|
+
s.extra_rdoc_files = ["History.txt", "README.rdoc", "lib/.loquacious.rb.swp", "lib/loquacious/.configuration.rb.swp"]
|
13
|
+
s.files = [".Rakefile.swp", ".gitignore", "History.txt", "README.rdoc", "Rakefile", "examples/gutters.rb", "examples/nested.rb", "examples/simple.rb", "lib/.loquacious.rb.swp", "lib/loquacious.rb", "lib/loquacious/.configuration.rb.swp", "lib/loquacious/configuration.rb", "lib/loquacious/configuration/help.rb", "lib/loquacious/configuration/iterator.rb", "lib/loquacious/core_ext/string.rb", "lib/loquacious/undefined.rb", "spec/configuration_spec.rb", "spec/help_spec.rb", "spec/iterator_spec.rb", "spec/loquacious_spec.rb", "spec/spec_helper.rb", "spec/string_spec.rb", "version.txt"]
|
14
|
+
s.homepage = "http://rubygems.org/gems/loquacious"
|
15
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = "loquacious"
|
18
|
+
s.rubygems_version = "1.8.10"
|
19
|
+
s.summary = "Descriptive configuration files for Ruby written in Ruby."
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
s.specification_version = 3
|
23
|
+
|
24
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
25
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.6"])
|
26
|
+
else
|
27
|
+
s.add_dependency(%q<rspec>, ["~> 2.6"])
|
28
|
+
end
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<rspec>, ["~> 2.6"])
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,513 @@
|
|
1
|
+
|
2
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
3
|
+
|
4
|
+
describe Loquacious::Configuration do
|
5
|
+
before(:each) do
|
6
|
+
@obj = Loquacious::Configuration.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should initialize from a block' do
|
10
|
+
obj = Loquacious::Configuration.new {
|
11
|
+
first 'foo'
|
12
|
+
second 'bar'
|
13
|
+
}
|
14
|
+
obj.first.eql?('foo').should be_true
|
15
|
+
obj.second.eql?('bar').should be_true
|
16
|
+
obj.third.kind_of?(Loquacious::Undefined).should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should respond to any method' do
|
20
|
+
@obj.first.kind_of?(Loquacious::Undefined).should be_true
|
21
|
+
@obj.first = 'foo'
|
22
|
+
@obj.first.eql?('foo').should be_true
|
23
|
+
|
24
|
+
@obj.second = 'bar'
|
25
|
+
@obj.second.eql?('bar').should be_true
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should deine attribute accessors when first used' do
|
29
|
+
@obj.respond_to?(:foo).should be_false
|
30
|
+
@obj.respond_to?(:foo=).should be_false
|
31
|
+
|
32
|
+
@obj.foo
|
33
|
+
@obj.respond_to?(:foo).should be_true
|
34
|
+
@obj.respond_to?(:foo=).should be_true
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should provide a hash object for storing method descriptions' do
|
38
|
+
h = @obj.__desc
|
39
|
+
@obj.__desc.should equal(h)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should allow attributes to be assigned hash values' do
|
43
|
+
cfg = Loquacious::Configuration.new {
|
44
|
+
hash({:one => 1})
|
45
|
+
}
|
46
|
+
cfg.hash.eql?({:one => 1}).should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should provide hash accessor notation for attributes' do
|
50
|
+
cfg = Loquacious::Configuration.new {
|
51
|
+
one 1
|
52
|
+
two 2
|
53
|
+
three 3
|
54
|
+
}
|
55
|
+
|
56
|
+
cfg['one'].eql?(1).should be_true
|
57
|
+
cfg[:two].eql?(2).should be_true
|
58
|
+
cfg['three'].eql?(3).should be_true
|
59
|
+
|
60
|
+
cfg[:four].kind_of?(Loquacious::Undefined).should be_true
|
61
|
+
cfg.four = 4
|
62
|
+
cfg[:four].eql?(4).should be_true
|
63
|
+
|
64
|
+
cfg[:five] = 5
|
65
|
+
cfg.five.eql?(5).should be_true
|
66
|
+
cfg[:five].eql?(5).should be_true
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should allow Kernel methods to be treated as configuration attributes' do
|
70
|
+
cfg = Loquacious::Configuration.new {
|
71
|
+
fork 'spoon knife spork'
|
72
|
+
split 'join'
|
73
|
+
raise 'double down'
|
74
|
+
puts 'not what you think'
|
75
|
+
}
|
76
|
+
|
77
|
+
cfg['fork'].eql?('spoon knife spork').should be_true
|
78
|
+
cfg['split'].eql?('join').should be_true
|
79
|
+
cfg['raise'].eql?('double down').should be_true
|
80
|
+
cfg['puts'].eql?('not what you think').should be_true
|
81
|
+
|
82
|
+
cfg[:fork].eql?('spoon knife spork').should be_true
|
83
|
+
cfg[:split].eql?('join').should be_true
|
84
|
+
cfg[:raise].eql?('double down').should be_true
|
85
|
+
cfg[:puts].eql?('not what you think').should be_true
|
86
|
+
|
87
|
+
cfg.fork.eql?('spoon knife spork').should be_true
|
88
|
+
cfg.split.eql?('join').should be_true
|
89
|
+
cfg.raise.eql?('double down').should be_true
|
90
|
+
cfg.puts.eql?('not what you think').should be_true
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should not be affected by loading other modules like timeout' do
|
94
|
+
require 'timeout'
|
95
|
+
Loquacious.remove :timeout
|
96
|
+
cfg = Loquacious::Configuration.new {
|
97
|
+
timeout 10
|
98
|
+
foo 'bar'
|
99
|
+
baz 'buz'
|
100
|
+
}
|
101
|
+
cfg.timeout.eql?(10).should be_true
|
102
|
+
cfg.foo.eql?('bar').should be_true
|
103
|
+
cfg.baz.eql?('buz').should be_true
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should evaluate Proc objects when fetching values' do
|
107
|
+
obj = Loquacious::Configuration.new {
|
108
|
+
first 'foo'
|
109
|
+
second 'bar'
|
110
|
+
}
|
111
|
+
|
112
|
+
obj.third = Proc.new { obj.first + obj.second }
|
113
|
+
obj.third.eql?('foobar').should be_true
|
114
|
+
|
115
|
+
obj.second = 'baz'
|
116
|
+
obj.third.eql?('foobaz').should be_true
|
117
|
+
|
118
|
+
obj.first = 'Hello '
|
119
|
+
obj.second = 'World!'
|
120
|
+
obj.third.eql?('Hello World!').should be_true
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should return a value when evaluating inside the DSL' do
|
124
|
+
obj = Loquacious::Configuration.new {
|
125
|
+
first 'foo'
|
126
|
+
second {
|
127
|
+
bar nil
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
obj.first.eql?('foo').should be_true
|
132
|
+
obj.second.bar.eql?(nil).should be_true
|
133
|
+
|
134
|
+
Loquacious::Configuration::DSL.evaluate(:config => obj) {
|
135
|
+
first 'bar'
|
136
|
+
second.bar 'no longer nil'
|
137
|
+
}
|
138
|
+
|
139
|
+
obj.first.eql?('bar').should be_true
|
140
|
+
obj.second.bar.eql?('no longer nil').should be_true
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should not delete descriptions' do
|
144
|
+
obj = Loquacious::Configuration.new {
|
145
|
+
first 'foo', :desc => 'the first value'
|
146
|
+
|
147
|
+
desc 'the second value'
|
148
|
+
second {
|
149
|
+
bar nil, :desc => 'time to go drinking'
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
obj.first.eql?('foo').should be_true
|
154
|
+
obj.second.bar.eql?(nil).should be_true
|
155
|
+
|
156
|
+
obj.__desc[:first].should be == 'the first value'
|
157
|
+
obj.__desc[:second].should be == 'the second value'
|
158
|
+
obj.second.__desc[:bar].should be == 'time to go drinking'
|
159
|
+
|
160
|
+
Loquacious::Configuration::DSL.evaluate(:config => obj) {
|
161
|
+
first 'bar'
|
162
|
+
second.bar 'no longer nil'
|
163
|
+
}
|
164
|
+
|
165
|
+
obj.first.eql?('bar').should be_true
|
166
|
+
obj.second.bar.eql?('no longer nil').should be_true
|
167
|
+
|
168
|
+
obj.__desc[:first].should be == 'the first value'
|
169
|
+
obj.__desc[:second].should be == 'the second value'
|
170
|
+
obj.second.__desc[:bar].should be == 'time to go drinking'
|
171
|
+
end
|
172
|
+
|
173
|
+
# -----------------------------------------------------------------------
|
174
|
+
describe 'when merging' do
|
175
|
+
before :each do
|
176
|
+
Loquacious::Configuration.instance_variable_get(:@table).clear
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'should merge the contents of another Configuration' do
|
180
|
+
other = Loquacious::Configuration.new {
|
181
|
+
first 'foo', :desc => 'foo method'
|
182
|
+
second 'bar', :desc => 'bar method'
|
183
|
+
}
|
184
|
+
|
185
|
+
@obj.first.kind_of?(Loquacious::Undefined).should be_true
|
186
|
+
@obj.second.kind_of?(Loquacious::Undefined).should be_true
|
187
|
+
@obj.__desc.should be == {:first => nil, :second => nil}
|
188
|
+
|
189
|
+
@obj.merge! other
|
190
|
+
@obj.first.eql?('foo').should be_true
|
191
|
+
@obj.second.eql?('bar').should be_true
|
192
|
+
@obj.__desc.should be == {
|
193
|
+
:first => 'foo method',
|
194
|
+
:second => 'bar method'
|
195
|
+
}
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'should recursively merge nested Configuration' do
|
199
|
+
other = Loquacious::Configuration.new {
|
200
|
+
first 'foo', :desc => 'foo method'
|
201
|
+
second 'bar', :desc => 'bar method'
|
202
|
+
|
203
|
+
desc 'the third group'
|
204
|
+
third {
|
205
|
+
answer 42, :desc => 'life the universe and everything'
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
@obj = Loquacious::Configuration.new {
|
210
|
+
third {
|
211
|
+
question '?', :desc => 'perhaps you do not understand'
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
@obj.merge! other
|
216
|
+
|
217
|
+
@obj.first.eql?('foo').should be_true
|
218
|
+
@obj.second.eql?('bar').should be_true
|
219
|
+
@obj.third.question.eql?('?').should be_true
|
220
|
+
@obj.third.answer.eql?(42).should be_true
|
221
|
+
|
222
|
+
@obj.__desc.should be == {
|
223
|
+
:first => 'foo method',
|
224
|
+
:second => 'bar method',
|
225
|
+
:third => 'the third group'
|
226
|
+
}
|
227
|
+
@obj.third.__desc.should be == {
|
228
|
+
:question => 'perhaps you do not understand',
|
229
|
+
:answer => 'life the universe and everything'
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'should raise an error when merging with an unknown object' do
|
234
|
+
lambda {@obj.merge! 'foo'}.
|
235
|
+
should raise_error(Loquacious::Configuration::Error, "can only merge another Configuration")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# -----------------------------------------------------------------------
|
240
|
+
describe 'when working with descriptions' do
|
241
|
+
|
242
|
+
it 'should consume leading whitespace' do
|
243
|
+
other = Loquacious::Configuration.new {
|
244
|
+
desc <<-STR
|
245
|
+
This is the first thing we are defining in this config.
|
246
|
+
It has a multiline comment.
|
247
|
+
STR
|
248
|
+
first 'foo'
|
249
|
+
second 'bar', :desc => "bar method\n also a multiline comment"
|
250
|
+
}
|
251
|
+
|
252
|
+
other.__desc[:first].should be == "This is the first thing we are defining in this config.\nIt has a multiline comment."
|
253
|
+
other.__desc[:second].should be == "bar method\nalso a multiline comment"
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'should leave whitespace after a gutter marker' do
|
257
|
+
other = Loquacious::Configuration.new {
|
258
|
+
desc <<-STR
|
259
|
+
| This is the first thing we are defining in this config.
|
260
|
+
| It has a multiline comment.
|
261
|
+
STR
|
262
|
+
first 'foo'
|
263
|
+
|
264
|
+
desc <<-DESC
|
265
|
+
This is a short explanation
|
266
|
+
|
267
|
+
Example:
|
268
|
+
| do this then that
|
269
|
+
| followed by this line
|
270
|
+
DESC
|
271
|
+
second 'bar'
|
272
|
+
}
|
273
|
+
|
274
|
+
other.__desc[:first].should be == " This is the first thing we are defining in this config.\n It has a multiline comment."
|
275
|
+
other.__desc[:second].should be == "This is a short explanation\n\nExample:\n do this then that\n followed by this line"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# -----------------------------------------------------------------------
|
280
|
+
describe 'when working with defaults' do
|
281
|
+
before :each do
|
282
|
+
Loquacious::Configuration.instance_variable_get(:@table).clear
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'returns default values when no other value exists' do
|
286
|
+
Loquacious::Configuration.defaults_for('test') {
|
287
|
+
first 'foo', :desc => 'the first value'
|
288
|
+
desc 'the second value'
|
289
|
+
second {
|
290
|
+
bar nil, :desc => 'time to go drinking'
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
c = Loquacious::Configuration.for 'test'
|
295
|
+
c.first.eql?('foo').should be_true
|
296
|
+
c.second.bar.eql?(nil).should be_true
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'does not overwrite existing configuration values' do
|
300
|
+
c = Loquacious::Configuration.for('test') {
|
301
|
+
first 1
|
302
|
+
third 3
|
303
|
+
}
|
304
|
+
|
305
|
+
Loquacious::Configuration.defaults_for('test') {
|
306
|
+
first 'foo', :desc => 'the first value'
|
307
|
+
desc 'the second value'
|
308
|
+
second {
|
309
|
+
bar nil, :desc => 'time to go drinking'
|
310
|
+
}
|
311
|
+
}
|
312
|
+
|
313
|
+
c.first.eql?(1).should be_true
|
314
|
+
c.third.eql?(3).should be_true
|
315
|
+
c.second.bar.eql?(nil).should be_true
|
316
|
+
|
317
|
+
c.__desc[:first].should be == 'the first value'
|
318
|
+
c.__desc[:second].should be == 'the second value'
|
319
|
+
c.second.__desc[:bar].should be == 'time to go drinking'
|
320
|
+
c.__desc[:third].should be_nil
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'does not overwrite nested configuration values' do
|
324
|
+
c = Loquacious::Configuration.for('test') {
|
325
|
+
first 1
|
326
|
+
second {
|
327
|
+
bar 'pub'
|
328
|
+
baz {
|
329
|
+
buz 'random text'
|
330
|
+
boo 'who'
|
331
|
+
}
|
332
|
+
}
|
333
|
+
third 3
|
334
|
+
}
|
335
|
+
|
336
|
+
Loquacious::Configuration.defaults_for('test') {
|
337
|
+
first 'foo', :desc => 'the first value'
|
338
|
+
desc 'the second value'
|
339
|
+
second {
|
340
|
+
bar 'h-bar', :desc => 'time to go drinking'
|
341
|
+
desc 'getting weird'
|
342
|
+
baz {
|
343
|
+
buz 'buz', :desc => 'post drinking feeling'
|
344
|
+
boo nil, :desc => 'no need to cry about it'
|
345
|
+
}
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
c.first.eql?(1).should be_true
|
350
|
+
c.third.eql?(3).should be_true
|
351
|
+
c.second.bar.eql?('pub').should be_true
|
352
|
+
c.second.baz.buz.eql?('random text').should be_true
|
353
|
+
c.second.baz.boo.eql?('who').should be_true
|
354
|
+
|
355
|
+
c.second.bar = Loquacious::Undefined.new('second.bar')
|
356
|
+
c.second.bar.eql?('h-bar').should be_true
|
357
|
+
|
358
|
+
c.__desc[:first].should be == 'the first value'
|
359
|
+
c.__desc[:second].should be == 'the second value'
|
360
|
+
c.second.__desc[:bar].should be == 'time to go drinking'
|
361
|
+
c.second.__desc[:baz].should be == 'getting weird'
|
362
|
+
c.second.baz.__desc[:buz].should be == 'post drinking feeling'
|
363
|
+
c.second.baz.__desc[:boo].should be == 'no need to cry about it'
|
364
|
+
c.__desc[:third].should be_nil
|
365
|
+
end
|
366
|
+
|
367
|
+
it 'supports differing default type' do
|
368
|
+
c = Loquacious::Configuration.for('test') {
|
369
|
+
first 1
|
370
|
+
second {
|
371
|
+
bar 'pub'
|
372
|
+
desc 'overwrite me'
|
373
|
+
baz {
|
374
|
+
buz 'random text'
|
375
|
+
boo 'who'
|
376
|
+
}
|
377
|
+
}
|
378
|
+
third 3
|
379
|
+
}
|
380
|
+
|
381
|
+
Loquacious::Configuration.defaults_for('test') {
|
382
|
+
first 'foo', :desc => 'the first value'
|
383
|
+
desc 'the second value'
|
384
|
+
second {
|
385
|
+
bar 'h-bar', :desc => 'time to go drinking'
|
386
|
+
baz nil, :desc => 'deprecated'
|
387
|
+
}
|
388
|
+
}
|
389
|
+
|
390
|
+
c.second.baz.buz.eql?('random text').should be_true
|
391
|
+
c.second.baz.boo.eql?('who').should be_true
|
392
|
+
|
393
|
+
c.second.baz = Loquacious::Undefined.new('second.bar')
|
394
|
+
c.second.baz.eql?(nil).should be_true
|
395
|
+
c.second.__desc[:baz].should be == 'deprecated'
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'properly handles Proc default values' do
|
399
|
+
c = Loquacious::Configuration.for('test') {
|
400
|
+
first 1
|
401
|
+
second {
|
402
|
+
bar 'pub'
|
403
|
+
}
|
404
|
+
third 3
|
405
|
+
}
|
406
|
+
|
407
|
+
Loquacious::Configuration.defaults_for('test') {
|
408
|
+
first 'foo', :desc => 'the first value'
|
409
|
+
desc 'the second value'
|
410
|
+
second {
|
411
|
+
bar 'h-bar', :desc => 'time to go drinking'
|
412
|
+
baz(Proc.new { c.third * 12 }, :desc => 'proc will be evaluated')
|
413
|
+
}
|
414
|
+
}
|
415
|
+
|
416
|
+
c.second.baz.eql?(36).should be_true
|
417
|
+
c.second.__desc[:baz].should be == 'proc will be evaluated'
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# -----------------------------------------------------------------------
|
422
|
+
describe 'when converting to a hash' do
|
423
|
+
it "should do so recursively" do
|
424
|
+
c = Loquacious::Configuration.new {
|
425
|
+
first 1, :desc => 'one is the loneliest number'
|
426
|
+
second {
|
427
|
+
bar 'pub', :desc => 'where the magic happens'
|
428
|
+
desc 'overwrite me'
|
429
|
+
baz {
|
430
|
+
buz 'random text'
|
431
|
+
boo 'who'
|
432
|
+
}
|
433
|
+
}
|
434
|
+
third 3
|
435
|
+
}
|
436
|
+
c.to_hash.should == {
|
437
|
+
:first => 1,
|
438
|
+
:second => {
|
439
|
+
:bar => 'pub',
|
440
|
+
:baz => {
|
441
|
+
:buz => 'random text',
|
442
|
+
:boo => 'who'
|
443
|
+
}
|
444
|
+
},
|
445
|
+
:third => 3
|
446
|
+
}
|
447
|
+
end
|
448
|
+
|
449
|
+
it "just returns an empty hash for an empty configuration" do
|
450
|
+
c = Loquacious::Configuration.new { }
|
451
|
+
c.to_hash.should == {}
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
# Added tests
|
456
|
+
describe "added features for ENV configuration" do
|
457
|
+
before(:all) do
|
458
|
+
Loquacious.env_config = true
|
459
|
+
end
|
460
|
+
after(:all) do
|
461
|
+
Loquacious.env_config = false
|
462
|
+
end
|
463
|
+
|
464
|
+
let(:obj) {
|
465
|
+
Loquacious.configuration_for('app') {
|
466
|
+
name :testing, :desc => "Defines the name", :transform => Proc.new{|arg| arg.to_sym }
|
467
|
+
foo 'bar', :desc => "FooBar"
|
468
|
+
id 42, :desc => "Ara T. Howard"
|
469
|
+
bar {
|
470
|
+
recur 'sive'
|
471
|
+
baz {
|
472
|
+
inner 'config'
|
473
|
+
}
|
474
|
+
}
|
475
|
+
}
|
476
|
+
}
|
477
|
+
|
478
|
+
it "sets the name for the created config" do
|
479
|
+
obj.__name.eql?("app").should be_true
|
480
|
+
end
|
481
|
+
|
482
|
+
it "sets the name for a nested object" do
|
483
|
+
obj.bar.__name.eql?("bar").should be_true
|
484
|
+
end
|
485
|
+
|
486
|
+
it "sets the parent name for a nested object" do
|
487
|
+
obj.bar.__parent.__name.eql?("app").should be_true
|
488
|
+
end
|
489
|
+
|
490
|
+
it "stores the transform for a configuration key" do
|
491
|
+
obj.__transforms[:name].is_a?(Proc).should be_true
|
492
|
+
end
|
493
|
+
|
494
|
+
it "overrides a value with the correct ENV value" do
|
495
|
+
ENV["LOQ_APP_FOO"] = "envbar"
|
496
|
+
obj.foo.eql?("envbar").should be_true
|
497
|
+
end
|
498
|
+
|
499
|
+
it "transforms the value using the provided lambda" do
|
500
|
+
ENV["LOQ_APP_NAME"] = "envname"
|
501
|
+
obj.name.eql?(:envname).should be_true
|
502
|
+
obj.name.is_a?(Symbol).should be_true
|
503
|
+
end
|
504
|
+
|
505
|
+
describe "#parent_list" do
|
506
|
+
it "returns the correct parent list for a configuration object" do
|
507
|
+
obj.bar.baz.parent_list.eql?(["app", "bar"]).should be_true
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
end#added features for ENV
|
512
|
+
end
|
513
|
+
|