iqeo-conf 1.0.1 → 1.1.0.pre.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -1
- data/lib/iqeo/configuration/version.rb +1 -1
- data/lib/iqeo/configuration.rb +58 -13
- data/spec/configuration_spec.rb +162 -7
- metadata +5 -5
data/README.md
CHANGED
@@ -121,12 +121,14 @@ conf.collect { |key,value| value } # => [ 1, 2.0, :three, 'four' ]
|
|
121
121
|
* defaults
|
122
122
|
* merge configurations recursively
|
123
123
|
* blank slate for DSL
|
124
|
+
* wildcard * for chained usage: a.b.*.d
|
124
125
|
|
125
|
-
##
|
126
|
+
## Application
|
126
127
|
|
127
128
|
* Dynamic settings by '[]' & '[]=' & 'self'
|
128
129
|
* Multiple configuration files
|
129
130
|
* Hierarchial configuration files
|
131
|
+
* Validation: if a.b.*.d == true
|
130
132
|
|
131
133
|
## License
|
132
134
|
|
data/lib/iqeo/configuration.rb
CHANGED
@@ -59,8 +59,8 @@ module Iqeo
|
|
59
59
|
#
|
60
60
|
# Content should be in eval DSL format.
|
61
61
|
|
62
|
-
def self.read string
|
63
|
-
conf = self.new
|
62
|
+
def self.read string, options = {}
|
63
|
+
conf = self.new nil, options
|
64
64
|
conf.instance_eval string
|
65
65
|
conf
|
66
66
|
end
|
@@ -69,12 +69,12 @@ module Iqeo
|
|
69
69
|
#
|
70
70
|
# Content should be in eval DSL format.
|
71
71
|
|
72
|
-
def self.load file
|
72
|
+
def self.load file, options = {}
|
73
73
|
return self.read file.respond_to?(:read) ? file.read : File.read(file)
|
74
74
|
end
|
75
75
|
|
76
|
-
def self.new_defer_block_for_parent parent, &block
|
77
|
-
conf = Configuration.new
|
76
|
+
def self.new_defer_block_for_parent parent, options = {}, &block
|
77
|
+
conf = Configuration.new nil, options
|
78
78
|
conf._parent = parent
|
79
79
|
if block_given? && block.arity > 0
|
80
80
|
block.call(conf) # this is 'yield self' from the outside
|
@@ -82,9 +82,18 @@ module Iqeo
|
|
82
82
|
conf
|
83
83
|
end
|
84
84
|
|
85
|
-
|
85
|
+
OPTIONS = {
|
86
|
+
:blankslate => true,
|
87
|
+
:case_sensitive => true
|
88
|
+
}
|
86
89
|
|
87
|
-
|
90
|
+
attr_accessor :_parent, :_items, :_options
|
91
|
+
|
92
|
+
# todo: why can't :_parent= be protected ?
|
93
|
+
#protected :_parent, :_items, :_items= #, :_get, :[], :_set, :[]=
|
94
|
+
|
95
|
+
def initialize default = nil, options = {}, &block
|
96
|
+
_process_options options
|
88
97
|
@_items = HashWithIndifferentAccess.new
|
89
98
|
@_parent = nil
|
90
99
|
_merge! default if default.kind_of?( Configuration )
|
@@ -105,11 +114,11 @@ module Iqeo
|
|
105
114
|
|
106
115
|
name = name.to_s.chomp('=')
|
107
116
|
|
108
|
-
if block_given?
|
109
|
-
if block.arity == 1
|
110
|
-
return _set name, Configuration.new_defer_block_for_parent( self, &block )
|
117
|
+
if block_given? # block is a nested configuration
|
118
|
+
if block.arity == 1 # yield DSL needs deferred block to set parent without binding
|
119
|
+
return _set name, Configuration.new_defer_block_for_parent( self, @_options, &block )
|
111
120
|
else
|
112
|
-
return _set name, Configuration.new( &block )
|
121
|
+
return _set name, Configuration.new( nil, @_options, &block ) # eval DSL can set parent from block binding in initialize
|
113
122
|
end
|
114
123
|
end
|
115
124
|
|
@@ -161,9 +170,45 @@ module Iqeo
|
|
161
170
|
self.dup._merge! other
|
162
171
|
end
|
163
172
|
|
164
|
-
|
173
|
+
def _configurations
|
174
|
+
@_items.values.select { |value| value.kind_of? Configuration }
|
175
|
+
end
|
176
|
+
|
177
|
+
def _process_options options
|
178
|
+
@_options = OPTIONS.merge options
|
179
|
+
#_wipe if @_options[:blankslate] # todo: how to make blankslate optional ?
|
180
|
+
end
|
181
|
+
|
182
|
+
# todo: method '*' for wildcard dir glob like selections eg top.*.bottom ?
|
183
|
+
|
184
|
+
def *
|
185
|
+
ConfigurationDelegator.new _configurations
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
165
189
|
|
166
|
-
|
190
|
+
class ConfigurationDelegator # todo: inherit from < Blankslate ?
|
191
|
+
|
192
|
+
attr_reader :_confs
|
193
|
+
|
194
|
+
# protected :_confs
|
195
|
+
|
196
|
+
def initialize confs
|
197
|
+
@_confs = confs
|
198
|
+
end
|
199
|
+
|
200
|
+
def method_missing name, *values, &block
|
201
|
+
return @_confs.send( name, *values, &block ) if @_confs.respond_to? name # @_confs methods are highest priority
|
202
|
+
end
|
203
|
+
#alias [] method_missing # so we don't have to deal with [ and 'key' separately ( see alias [] _get in Configuration )
|
204
|
+
|
205
|
+
def empty?
|
206
|
+
@_confs.empty?
|
207
|
+
end
|
208
|
+
|
209
|
+
def *
|
210
|
+
ConfigurationDelegator.new( @_confs.inject([]) { |array,conf| array + conf._configurations } )
|
211
|
+
end
|
167
212
|
|
168
213
|
end
|
169
214
|
|
data/spec/configuration_spec.rb
CHANGED
@@ -951,13 +951,168 @@ describe Configuration do
|
|
951
951
|
|
952
952
|
end # "v1.0"
|
953
953
|
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
954
|
+
def simple_config_1
|
955
|
+
Configuration.new do
|
956
|
+
alpha 1
|
957
|
+
bravo 'one'
|
958
|
+
charlie 1.0
|
959
|
+
delta :one
|
960
|
+
end
|
961
|
+
end
|
962
|
+
|
963
|
+
def simple_config_1_example conf
|
964
|
+
conf.should_not be_nil
|
965
|
+
conf.alpha.should == 1 and conf.alpha.should be_a Fixnum
|
966
|
+
conf.bravo.should == "one" and conf.bravo.should be_a String
|
967
|
+
conf.charlie.should == 1.0 and conf.charlie.should be_a Float
|
968
|
+
conf.delta.should == :one and conf.delta.should be_a Symbol
|
969
|
+
end
|
970
|
+
|
971
|
+
def simple_config_2
|
972
|
+
Configuration.new do
|
973
|
+
echo 2
|
974
|
+
foxtrot 'two'
|
975
|
+
hotel 2.0
|
976
|
+
india :two
|
977
|
+
end
|
978
|
+
end
|
979
|
+
|
980
|
+
def simple_config_2_example conf
|
981
|
+
conf.should_not be_nil
|
982
|
+
conf.echo.should == 2 and conf.echo.should be_a Fixnum
|
983
|
+
conf.foxtrot.should == "two" and conf.foxtrot.should be_a String
|
984
|
+
conf.hotel.should == 2.0 and conf.hotel.should be_a Float
|
985
|
+
conf.india.should == :two and conf.india.should be_a Symbol
|
986
|
+
conf['echo']
|
987
|
+
#and conf[:echo].should be_a Fixnum
|
988
|
+
|
989
|
+
end
|
990
|
+
|
991
|
+
def simple_config_3
|
992
|
+
Configuration.new do
|
993
|
+
juliet 3
|
994
|
+
kilo 'three'
|
995
|
+
lima 3.0
|
996
|
+
mike :three
|
997
|
+
end
|
998
|
+
end
|
999
|
+
|
1000
|
+
def simple_config_3_example conf
|
1001
|
+
conf.should_not be_nil
|
1002
|
+
conf.juliet.should == 3 and conf.juliet.should be_a Fixnum
|
1003
|
+
conf.kilo.should == "three" and conf.kilo.should be_a String
|
1004
|
+
conf.lima.should == 3.0 and conf.lima.should be_a Float
|
1005
|
+
conf.mike.should == :three and conf.mike.should be_a Symbol
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
context 'v1.1' do
|
1009
|
+
|
1010
|
+
context 'options' do
|
1011
|
+
|
1012
|
+
it 'have defaults at Configuration creation' do
|
1013
|
+
conf = Configuration.new
|
1014
|
+
conf._options[:blankslate].should be true
|
1015
|
+
conf._options[:case_sensitive].should be true
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
it 'are accepted at Configuration creation' do
|
1019
|
+
conf = Configuration.new nil, :blankslate => false, :case_sensitive => false
|
1020
|
+
conf._options[:blankslate].should be false
|
1021
|
+
conf._options[:case_sensitive].should be false
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
context 'wildcard *' do
|
1027
|
+
|
1028
|
+
it 'returns an empty ConfigurationDelegator for subject with no child configurations' do
|
1029
|
+
conf = simple_config_1
|
1030
|
+
simple_config_1_example conf
|
1031
|
+
delegator = conf.*
|
1032
|
+
delegator.should be_a ConfigurationDelegator
|
1033
|
+
delegator.should be_empty
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
it 'returns ConfigurationDelegator containing child configurations for subject' do
|
1037
|
+
conf = simple_config_1
|
1038
|
+
conf.nested2 = simple_config_2
|
1039
|
+
conf.nested3 = simple_config_3
|
1040
|
+
simple_config_1_example conf
|
1041
|
+
simple_config_2_example conf.nested2
|
1042
|
+
simple_config_3_example conf.nested3
|
1043
|
+
delegator = conf.*
|
1044
|
+
delegator.should be_a ConfigurationDelegator
|
1045
|
+
delegator.size.should be 2
|
1046
|
+
delegator[0].should be conf.nested2
|
1047
|
+
delegator[1].should be conf.nested3
|
1048
|
+
end
|
1049
|
+
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
context 'ConfigurationDelegator' do
|
1053
|
+
|
1054
|
+
it 'can be created with no child configurations' do
|
1055
|
+
delegator = ConfigurationDelegator.new []
|
1056
|
+
delegator.should be_a ConfigurationDelegator
|
1057
|
+
delegator.should be_empty
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
context 'wildcard *' do
|
1061
|
+
|
1062
|
+
# todo: question : should wildcard return nil for already empty ConfigurationDelegator / overshoot ?
|
1063
|
+
|
1064
|
+
it 'returns an empty ConfigurationDelegator for ConfigurationDelegator with no child configurations' do
|
1065
|
+
conf = simple_config_1
|
1066
|
+
conf.nested2 = simple_config_2
|
1067
|
+
conf.nested3 = simple_config_3
|
1068
|
+
simple_config_1_example conf
|
1069
|
+
simple_config_2_example conf.nested2
|
1070
|
+
simple_config_3_example conf.nested3
|
1071
|
+
delegator = conf.*.*
|
1072
|
+
delegator.should be_a ConfigurationDelegator
|
1073
|
+
delegator.should be_empty
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
it 'returns an empty ConfigurationDelegator when overshoots' do
|
1077
|
+
conf = simple_config_1
|
1078
|
+
conf.nested2 = simple_config_2
|
1079
|
+
conf.nested3 = simple_config_3
|
1080
|
+
simple_config_1_example conf
|
1081
|
+
simple_config_2_example conf.nested2
|
1082
|
+
simple_config_3_example conf.nested3
|
1083
|
+
delegator = conf.*.*.*.*.*.*.*.*.*
|
1084
|
+
delegator.should be_a ConfigurationDelegator
|
1085
|
+
delegator.should be_empty
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
it 'returns ConfigurationDelegator containing child configurations for ConfigurationDelegator' do
|
1089
|
+
conf = simple_config_1
|
1090
|
+
conf.nested2 = simple_config_2
|
1091
|
+
conf.nested3 = simple_config_3
|
1092
|
+
conf.nested2.nested2 = simple_config_2
|
1093
|
+
conf.nested2.nested3 = simple_config_3
|
1094
|
+
conf.nested3.nested2 = simple_config_2
|
1095
|
+
conf.nested3.nested3 = simple_config_3
|
1096
|
+
simple_config_1_example conf
|
1097
|
+
simple_config_2_example conf.nested2
|
1098
|
+
simple_config_2_example conf.nested2.nested2
|
1099
|
+
simple_config_2_example conf.nested3.nested2
|
1100
|
+
simple_config_3_example conf.nested3
|
1101
|
+
simple_config_3_example conf.nested2.nested3
|
1102
|
+
simple_config_3_example conf.nested3.nested3
|
1103
|
+
delegator = conf.*.*
|
1104
|
+
delegator.size.should be 4
|
1105
|
+
delegator[0].should be conf.nested2.nested2
|
1106
|
+
delegator[1].should be conf.nested2.nested3
|
1107
|
+
delegator[2].should be conf.nested3.nested2
|
1108
|
+
delegator[3].should be conf.nested3.nested3
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
end # wildcard *
|
1112
|
+
|
1113
|
+
end # ConfigurationDelagator
|
1114
|
+
|
1115
|
+
end #v1.1
|
961
1116
|
|
962
1117
|
end
|
963
1118
|
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iqeo-conf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.1.0.pre.0
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Gerard Fowley
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -146,9 +146,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
146
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
147
|
none: false
|
148
148
|
requirements:
|
149
|
-
- - ! '
|
149
|
+
- - ! '>'
|
150
150
|
- !ruby/object:Gem::Version
|
151
|
-
version:
|
151
|
+
version: 1.3.1
|
152
152
|
requirements: []
|
153
153
|
rubyforge_project:
|
154
154
|
rubygems_version: 1.8.24
|