configurable 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,16 +1,12 @@
1
1
  module Configurable
2
2
 
3
- # Utility methods to dump and load configurations, particularly nested
4
- # configurations.
3
+ # Utility methods to dump and load Configurable class configurations.
5
4
  module Utils
6
5
  module_function
7
6
 
8
- default_dump_block = lambda do |key, delegate|
9
- default = delegate.default(false)
10
-
7
+ default_dump_block = lambda do |key, config|
11
8
  # note: this causes order to be lost...
12
- default = default.to_hash if delegate.is_nest?
13
- YAML.dump({key => default})[5..-1]
9
+ YAML.dump({key => config.default})[5..-1]
14
10
  end
15
11
 
16
12
  # A block performing the default YAML dump.
@@ -23,9 +19,9 @@ module Configurable
23
19
  # A block performing the default load.
24
20
  DEFAULT_LOAD = default_load_block
25
21
 
26
- # Dumps delegates to target as yaml. Delegates are output in order, and
27
- # symbol keys are be stringified if delegates has been extended with
28
- # IndifferentAccess (this produces a nicer config file).
22
+ # Dumps configurations to target as yaml. Configs are output in order,
23
+ # and symbol keys are be stringified if configurations has been extended
24
+ # with IndifferentAccess (this produces a nicer config file).
29
25
  #
30
26
  # class DumpExample
31
27
  # include Configurable
@@ -40,7 +36,7 @@ module Configurable
40
36
  # # str: value
41
37
  # # }
42
38
  #
43
- # Dump may be provided with a block to format each (key, delegate) pair;
39
+ # Dump may be provided with a block to format each (key, Config) pair;
44
40
  # the block results are pushed directly to target, so newlines must be
45
41
  # specified manually.
46
42
  #
@@ -57,27 +53,27 @@ module Configurable
57
53
  # #
58
54
  # # }
59
55
  #
60
- def dump(delegates, target="")
61
- return dump(delegates, target, &DEFAULT_DUMP) unless block_given?
56
+ def dump(configs, target="")
57
+ return dump(configs, target, &DEFAULT_DUMP) unless block_given?
62
58
 
63
- stringify = delegates.kind_of?(IndifferentAccess)
64
- delegates.each_pair do |key, delegate|
59
+ stringify = configs.kind_of?(IndifferentAccess)
60
+ configs.each_pair do |key, config|
65
61
  key = key.to_s if stringify && key.kind_of?(Symbol)
66
- target << yield(key, delegate)
62
+ target << yield(key, config)
67
63
  end
68
64
 
69
65
  target
70
66
  end
71
67
 
72
- # Dumps the delegates to the specified file. If recurse is true, nested
73
- # configurations are each dumped to their own file, based on the nesting
68
+ # Dumps the configurations to the specified file. If recurse is true,
69
+ # nested configs are each dumped to their own file, based on the nesting
74
70
  # key. For instance if you nested a in b:
75
71
  #
76
72
  # a_configs = {
77
- # 'key' => Delegate.new(:r, :w, 'a default')}
73
+ # 'key' => Config.new(:r, :w, 'a default')}
78
74
  # b_configs = {
79
- # 'key' => Delegate.new(:r, :w, 'b default')}
80
- # 'a' => Delegate.new(:r, :w, DelegateHash.new(a_configs))}}
75
+ # 'key' => Config.new(:r, :w, 'b default')}
76
+ # 'a' => Config.new(:r, :w, ConfigHash.new(a_configs))}}
81
77
  #
82
78
  # Utils.dump_file(b_configs, 'b.yml')
83
79
  # File.read('b.yml') # => "key: b default"
@@ -93,28 +89,25 @@ module Configurable
93
89
  # preview dumps are always returned by dump_file.
94
90
  #
95
91
  # ==== Note
96
- # For load_file to correctly load a recursive dump, all delegate hashes
97
- # must use String keys. Symbol keys are allowed if the delegate hashes use
92
+ # For load_file to correctly load a recursive dump, all config hashes
93
+ # must use String keys. Symbol keys are allowed if the config hashes use
98
94
  # IndifferentAccess; all other keys will not load properly. By default
99
95
  # Configurable is set up to satisfy these conditions.
100
96
  #
101
97
  # 1.8 Bug: Currently dump_file with recurse=false will cause order to be
102
98
  # lost in nested configs. See http://bahuvrihi.lighthouseapp.com/projects/21202-configurable/tickets/8
103
- def dump_file(delegates, path, recurse=false, preview=false, &block)
104
- return dump_file(delegates, path, recurse, preview, &DEFAULT_DUMP) unless block_given?
99
+ def dump_file(configs, path, recurse=false, preview=false, &block)
100
+ return dump_file(configs, path, recurse, preview, &DEFAULT_DUMP) unless block_given?
105
101
 
106
102
  current = ""
107
103
  dumps = [[path, current]]
108
104
 
109
- dump(delegates, current) do |key, delegate|
110
- if recurse && delegate.is_nest?
111
- nested_delegates = delegate.default(false).delegates
112
- nested_dumps = dump_file(nested_delegates, recursive_path(key, path), true, true, &block)
113
-
114
- dumps.concat(nested_dumps)
105
+ dump(configs, current) do |key, config|
106
+ if recurse && config.kind_of?(NestConfig)
107
+ dumps.concat(dump_file(config.nest_class.configurations, recursive_path(key, path), true, true, &block))
115
108
  ""
116
109
  else
117
- yield(key, delegate)
110
+ yield(key, config)
118
111
  end
119
112
  end
120
113
 
@@ -8,7 +8,7 @@ module Configurable
8
8
 
9
9
  # Validation generates blocks for common validations and transformations of
10
10
  # configurations set through Configurable. In general these blocks load
11
- # string inputs as YAML and valdiate the results; non-string inputs are
11
+ # string inputs as YAML and validate the results; non-string inputs are
12
12
  # simply validated.
13
13
  #
14
14
  # integer = Validation.integer
@@ -56,7 +56,7 @@ module Configurable
56
56
 
57
57
  # Registers the default attributes with the specified block
58
58
  # in Configurable::DEFAULT_ATTRIBUTES.
59
- def register(block, attributes)
59
+ def register(attributes={}, &block)
60
60
  DEFAULT_ATTRIBUTES[block] = attributes
61
61
  block
62
62
  end
@@ -207,7 +207,7 @@ module Configurable
207
207
 
208
208
  # default attributes {:type => :string, :example => "string"}
209
209
  STRING = string_validation_block
210
- register STRING, :type => :string, :example => "string"
210
+ register :type => :string, :example => "string", &STRING
211
211
 
212
212
  # Same as string but allows nil. Note the special
213
213
  # behavior of the nil string '~' -- rather than
@@ -242,7 +242,7 @@ module Configurable
242
242
 
243
243
  # default attributes {:type => :symbol, :example => ":sym"}
244
244
  SYMBOL = yaml(Symbol)
245
- register SYMBOL, :type => :symbol, :example => ":sym"
245
+ register :type => :symbol, :example => ":sym", &SYMBOL
246
246
 
247
247
  # Same as symbol but allows nil:
248
248
  #
@@ -253,6 +253,46 @@ module Configurable
253
253
  SYMBOL_OR_NIL = yaml(Symbol, nil)
254
254
  register_as SYMBOL, SYMBOL_OR_NIL
255
255
 
256
+ # Returns a block that checks the input is a symbol.
257
+ # String inputs are directly converted to a symbol.
258
+ #
259
+ # strbol.class # => Proc
260
+ # strbol.call(:sym) # => :sym
261
+ # strbol.call(':sym') # => :":sym"
262
+ # strbol.call('str') # => :sym
263
+ # strbol.call(nil) # => ValidationError
264
+ #
265
+ def strbol(); STRBOL; end
266
+
267
+ # default attributes {:type => :symbol, :example => ":sym"}
268
+ STRBOL = lambda do |input|
269
+ if input.kind_of?(String)
270
+ input = input.to_sym
271
+ end
272
+
273
+ validate(input, [Symbol])
274
+ end
275
+ register :type => :symbol, :example => ":sym", &STRBOL
276
+
277
+ # Same as strbol but allows nil. Tilde is considered a string
278
+ # equivalent of nil (this behavior is consistent with the YAML
279
+ # methods but obviously inconsistent with the strbol behavior).
280
+ #
281
+ # strbol_or_nil.call('~') # => nil
282
+ # strbol_or_nil.call(nil) # => nil
283
+ def strbol_or_nil(); STRBOL_OR_NIL; end
284
+
285
+ STRBOL_OR_NIL = lambda do |input|
286
+ input = case input
287
+ when "~" then nil
288
+ when String then input.to_sym
289
+ else input
290
+ end
291
+
292
+ validate(input, [Symbol, nil])
293
+ end
294
+ register_as STRBOL, STRBOL_OR_NIL
295
+
256
296
  # Returns a block that checks the input is true, false or nil.
257
297
  # String inputs are loaded as yaml first.
258
298
  #
@@ -272,21 +312,21 @@ module Configurable
272
312
 
273
313
  # default attributes {:type => :boolean, :example => "true, yes"}
274
314
  BOOLEAN = yaml(true, false, nil)
275
- register BOOLEAN, :type => :boolean, :example => "true, yes"
315
+ register :type => :boolean, :example => "true, yes", &BOOLEAN
276
316
 
277
317
  # Same as boolean.
278
318
  def switch(); SWITCH; end
279
319
 
280
320
  # default attributes {:type => :switch}
281
321
  SWITCH = yaml(true, false, nil)
282
- register SWITCH, :type => :switch
322
+ register :type => :switch, &SWITCH
283
323
 
284
324
  # Same as boolean.
285
325
  def flag(); FLAG; end
286
326
 
287
327
  # default attributes {:type => :flag}
288
328
  FLAG = yaml(true, false, nil)
289
- register FLAG, :type => :flag
329
+ register :type => :flag, &FLAG
290
330
 
291
331
  # Returns a block that checks the input is an array.
292
332
  # String inputs are loaded as yaml first.
@@ -301,7 +341,7 @@ module Configurable
301
341
 
302
342
  # default attributes {:type => :array, :example => "[a, b, c]"}
303
343
  ARRAY = yaml(Array)
304
- register ARRAY, :type => :array, :example => "[a, b, c]"
344
+ register :type => :array, :example => "[a, b, c]", &ARRAY
305
345
 
306
346
  # Same as array but allows nil:
307
347
  #
@@ -343,7 +383,7 @@ module Configurable
343
383
 
344
384
  # default attributes {:type => :list, :split => ','}
345
385
  LIST = list_block
346
- register LIST, :type => :list, :split => ','
386
+ register :type => :list, :split => ',', &LIST
347
387
 
348
388
  # Returns a block that checks the input is a hash.
349
389
  # String inputs are loaded as yaml first.
@@ -358,7 +398,7 @@ module Configurable
358
398
 
359
399
  # default attributes {:type => :hash, :example => "{one: 1, two: 2}"}
360
400
  HASH = yaml(Hash)
361
- register HASH, :type => :hash, :example => "{one: 1, two: 2}"
401
+ register :type => :hash, :example => "{one: 1, two: 2}", &HASH
362
402
 
363
403
  # Same as hash but allows nil:
364
404
  #
@@ -383,7 +423,7 @@ module Configurable
383
423
 
384
424
  # default attributes {:type => :integer, :example => "2"}
385
425
  INTEGER = yaml(Integer)
386
- register INTEGER, :type => :integer, :example => "2"
426
+ register :type => :integer, :example => "2", &INTEGER
387
427
 
388
428
  # Same as integer but allows nil:
389
429
  #
@@ -409,7 +449,7 @@ module Configurable
409
449
 
410
450
  # default attributes {:type => :float, :example => "2.2, 2.0e+2"}
411
451
  FLOAT = yaml(Float)
412
- register FLOAT, :type => :float, :example => "2.2, 2.0e+2"
452
+ register :type => :float, :example => "2.2, 2.0e+2", &FLOAT
413
453
 
414
454
  # Same as float but allows nil:
415
455
  #
@@ -436,7 +476,7 @@ module Configurable
436
476
 
437
477
  # default attributes {:type => :numeric, :example => "2, 2.2, 2.0e+2"}
438
478
  NUMERIC = yaml(Numeric)
439
- register NUMERIC, :type => :numeric, :example => "2, 2.2, 2.0e+2"
479
+ register :type => :numeric, :example => "2, 2.2, 2.0e+2", &NUMERIC
440
480
 
441
481
  # Same as numeric but allows nil:
442
482
  #
@@ -477,7 +517,7 @@ module Configurable
477
517
 
478
518
  # default attributes {:type => :regexp, :example => "/regexp/i"}
479
519
  REGEXP = regexp_block
480
- register REGEXP, :type => :regexp, :example => "/regexp/i"
520
+ register :type => :regexp, :example => "/regexp/i", &REGEXP
481
521
 
482
522
  # Same as regexp but allows nil. Note the special behavior of the nil
483
523
  # string '~' -- rather than being converted to a regexp, it is processed
@@ -524,7 +564,7 @@ module Configurable
524
564
 
525
565
  # default attributes {:type => :range, :example => "min..max"}
526
566
  RANGE = range_block
527
- register RANGE, :type => :range, :example => "min..max"
567
+ register :type => :range, :example => "min..max", &RANGE
528
568
 
529
569
  # Same as range but allows nil:
530
570
  #
@@ -579,7 +619,7 @@ module Configurable
579
619
 
580
620
  # default attributes {:type => :time, :example => "2008-08-08 08:00:00"}
581
621
  TIME = time_block
582
- register TIME, :type => :time, :example => "2008-08-08 08:00:00"
622
+ register :type => :time, :example => "2008-08-08 08:00:00", &TIME
583
623
 
584
624
  # Same as time but allows nil:
585
625
  #
@@ -614,15 +654,14 @@ module Configurable
614
654
  # {:type => :select, :options => options}
615
655
  #
616
656
  def select(*options, &validation)
617
- block = lambda do |input|
657
+ register(
658
+ :type => :select,
659
+ :options => options,
660
+ :validation => attributes(validation)
661
+ ) do |input|
618
662
  input = validation.call(input) if validation
619
663
  validate(input, options)
620
664
  end
621
-
622
- register(block,
623
- :type => :select,
624
- :options => options,
625
- :validation => attributes(validation))
626
665
  end
627
666
 
628
667
  # Returns a block that checks the input is an array, and that each member
@@ -645,17 +684,16 @@ module Configurable
645
684
  # {:type => :list_select, :options => options, :split => ','}
646
685
  #
647
686
  def list_select(*options, &validation)
648
- block = lambda do |input|
687
+ register(
688
+ :type => :list_select,
689
+ :options => options,
690
+ :split => ',',
691
+ :validation => attributes(validation)
692
+ ) do |input|
649
693
  args = validate(input, [Array])
650
694
  args.collect! {|arg| validation.call(arg) } if validation
651
695
  args.each {|arg| validate(arg, options) }
652
696
  end
653
-
654
- register(block,
655
- :type => :list_select,
656
- :options => options,
657
- :split => ',',
658
- :validation => attributes(validation))
659
697
  end
660
698
 
661
699
  # Returns a block validating the input is an IO, a string, or an integer.
@@ -693,9 +731,9 @@ module Configurable
693
731
  end
694
732
  end
695
733
 
696
- # default attributes {:type => :io, :duplicate_default => false, :example => "/path/to/file"}
734
+ # default attributes {:type => :io, :dup => false, :example => "/path/to/file"}
697
735
  IO_OR_STRING = check(IO, String, Integer)
698
- register IO_OR_STRING, :type => :io, :duplicate_default => false, :example => "/path/to/file"
736
+ register :type => :io, :dup => false, :example => "/path/to/file", &IO_OR_STRING
699
737
 
700
738
  # Same as io but allows nil:
701
739
  #
@@ -0,0 +1,7 @@
1
+ module Configurable
2
+ MAJOR = 0
3
+ MINOR = 6
4
+ TINY = 0
5
+
6
+ VERSION="#{MAJOR}.#{MINOR}.#{TINY}"
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configurable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Chiang
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-25 00:00:00 -06:00
12
+ date: 2009-12-05 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.9.0
23
+ version: 1.0.0
24
24
  version:
25
25
  description:
26
26
  email: simon.a.chiang@gmail.com
@@ -42,17 +42,22 @@ files:
42
42
  - lib/config_parser/utils.rb
43
43
  - lib/configurable.rb
44
44
  - lib/configurable/class_methods.rb
45
- - lib/configurable/delegate.rb
46
- - lib/configurable/delegate_hash.rb
45
+ - lib/configurable/config.rb
46
+ - lib/configurable/config_hash.rb
47
47
  - lib/configurable/indifferent_access.rb
48
48
  - lib/configurable/module_methods.rb
49
- - lib/configurable/validation.rb
49
+ - lib/configurable/nest_config.rb
50
+ - lib/configurable/ordered_hash_patch.rb
50
51
  - lib/configurable/utils.rb
52
+ - lib/configurable/validation.rb
53
+ - lib/configurable/version.rb
51
54
  - MIT-LICENSE
52
55
  - README
53
56
  - History
54
57
  has_rdoc: true
55
58
  homepage: http://tap.rubyforge.org/configurable
59
+ licenses: []
60
+
56
61
  post_install_message:
57
62
  rdoc_options:
58
63
  - --title
@@ -78,9 +83,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
83
  requirements: []
79
84
 
80
85
  rubyforge_project: tap
81
- rubygems_version: 1.3.1
86
+ rubygems_version: 1.3.5
82
87
  signing_key:
83
- specification_version: 2
88
+ specification_version: 3
84
89
  summary: configurable
85
90
  test_files: []
86
91
 
@@ -1,103 +0,0 @@
1
- module Configurable
2
-
3
- # Delegates are used by DelegateHash to determine how to map read/write
4
- # operations to a receiver.
5
- class Delegate
6
- class << self
7
-
8
- # Determines if the value is duplicable. Non-duplicable
9
- # values include nil, true, false, Symbol, Numeric, and
10
- # any object that does not respond to dup.
11
- def duplicable_value?(value)
12
- case value
13
- when nil, true, false, Symbol, Numeric, Method then false
14
- else value.respond_to?(:dup)
15
- end
16
- end
17
- end
18
-
19
- # The reader method, by default key
20
- attr_reader :reader
21
-
22
- # The writer method, by default key=
23
- attr_reader :writer
24
-
25
- # An hash of metadata for self, used to present the delegate in different
26
- # contexts (ex on the command line, in a web form, or a desktop app).
27
- # Note that attributes should be set through []= and not through this
28
- # reader.
29
- attr_reader :attributes
30
-
31
- # Initializes a new Delegate with the specified key and default value.
32
- def initialize(reader, writer="#{reader}=", default=nil, attributes={})
33
- @attributes = attributes
34
-
35
- self.default = default
36
- self.reader = reader
37
- self.writer = writer
38
- end
39
-
40
- # Sets the value of an attribute.
41
- def []=(key, value)
42
- attributes[key] = value
43
- reset_duplicable if key == :duplicate_default
44
- end
45
-
46
- # Returns the value for the specified attribute, or
47
- # default, if the attribute is unspecified.
48
- def [](key, default=nil)
49
- attributes.has_key?(key) ? attributes[key] : default
50
- end
51
-
52
- # Sets the default value for self.
53
- def default=(value)
54
- @default = value
55
- reset_duplicable
56
- end
57
-
58
- # Returns the default value, or a duplicate of the default value if specified.
59
- # The default value will not be duplicated unless duplicable (see
60
- # Delegate.duplicable_value?). Duplication can also be turned off by
61
- # specifying self[:duplicate_default] = false.
62
- def default(duplicate=true)
63
- duplicate && @duplicable ? @default.dup : @default
64
- end
65
-
66
- # Sets the reader for self.
67
- def reader=(value)
68
- raise ArgumentError, "reader may not be nil" if value == nil
69
- @reader = value.to_sym
70
- end
71
-
72
- # Sets the writer for self.
73
- def writer=(value)
74
- raise ArgumentError, "writer may not be nil" if value == nil
75
- @writer = value.to_sym
76
- end
77
-
78
- # Returns true if the default value is a kind of DelegateHash.
79
- def is_nest?
80
- @default.kind_of?(DelegateHash)
81
- end
82
-
83
- # True if another is a kind of Delegate with the same
84
- # reader, writer, and default value. Attributes are
85
- # not considered.
86
- def ==(another)
87
- another.kind_of?(Delegate) &&
88
- self.reader == another.reader &&
89
- self.writer == another.writer &&
90
- self.default(false) == another.default(false)
91
- end
92
-
93
- private
94
-
95
- # resets marker indiciating whether or not a default value is duplicable
96
- def reset_duplicable # :nodoc:
97
- @duplicable = case attributes[:duplicate_default]
98
- when true, nil then Delegate.duplicable_value?(@default)
99
- else false
100
- end
101
- end
102
- end
103
- end