tap 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/History +35 -1
  2. data/MIT-LICENSE +1 -1
  3. data/README +16 -15
  4. data/bin/tap +1 -1
  5. data/cmd/console.rb +4 -3
  6. data/cmd/manifest.rb +2 -2
  7. data/cmd/run.rb +12 -15
  8. data/doc/Class Reference +120 -117
  9. data/doc/Command Reference +27 -27
  10. data/doc/Syntax Reference +55 -111
  11. data/doc/Tutorial +69 -26
  12. data/lib/tap.rb +3 -8
  13. data/lib/tap/app.rb +122 -146
  14. data/lib/tap/constants.rb +2 -2
  15. data/lib/tap/env.rb +178 -252
  16. data/lib/tap/exe.rb +67 -30
  17. data/lib/tap/file_task.rb +224 -411
  18. data/lib/tap/generator/arguments.rb +13 -0
  19. data/lib/tap/generator/base.rb +112 -30
  20. data/lib/tap/generator/destroy.rb +36 -13
  21. data/lib/tap/generator/generate.rb +69 -48
  22. data/lib/tap/generator/generators/command/templates/command.erb +3 -3
  23. data/lib/tap/generator/generators/config/config_generator.rb +82 -10
  24. data/lib/tap/generator/generators/generator/generator_generator.rb +16 -6
  25. data/lib/tap/generator/generators/generator/templates/task.erb +2 -2
  26. data/lib/tap/generator/generators/generator/templates/test.erb +26 -0
  27. data/lib/tap/generator/generators/root/root_generator.rb +24 -13
  28. data/lib/tap/generator/generators/root/templates/Rakefile +4 -4
  29. data/lib/tap/generator/generators/root/templates/{tapfile → Rapfile} +6 -6
  30. data/lib/tap/generator/generators/root/templates/gemspec +0 -1
  31. data/lib/tap/generator/generators/task/task_generator.rb +3 -3
  32. data/lib/tap/generator/generators/task/templates/test.erb +1 -1
  33. data/lib/tap/generator/manifest.rb +7 -1
  34. data/lib/tap/generator/preview.rb +76 -0
  35. data/lib/tap/root.rb +222 -156
  36. data/lib/tap/spec.rb +41 -0
  37. data/lib/tap/support/aggregator.rb +25 -28
  38. data/lib/tap/support/audit.rb +278 -357
  39. data/lib/tap/support/constant.rb +2 -1
  40. data/lib/tap/support/constant_manifest.rb +28 -25
  41. data/lib/tap/support/dependency.rb +1 -1
  42. data/lib/tap/support/executable.rb +52 -183
  43. data/lib/tap/support/executable_queue.rb +50 -20
  44. data/lib/tap/support/gems.rb +1 -1
  45. data/lib/tap/support/intern.rb +0 -6
  46. data/lib/tap/support/join.rb +49 -83
  47. data/lib/tap/support/joins.rb +0 -3
  48. data/lib/tap/support/joins/switch.rb +13 -11
  49. data/lib/tap/support/joins/sync_merge.rb +25 -50
  50. data/lib/tap/support/manifest.rb +1 -0
  51. data/lib/tap/support/node.rb +140 -20
  52. data/lib/tap/support/parser.rb +56 -42
  53. data/lib/tap/support/schema.rb +183 -157
  54. data/lib/tap/support/templater.rb +9 -1
  55. data/lib/tap/support/versions.rb +39 -0
  56. data/lib/tap/task.rb +150 -177
  57. data/lib/tap/tasks/dump.rb +4 -4
  58. data/lib/tap/tasks/load.rb +29 -29
  59. data/lib/tap/test.rb +66 -53
  60. data/lib/tap/test/env_vars.rb +3 -3
  61. data/lib/tap/test/extensions.rb +11 -17
  62. data/lib/tap/test/file_test.rb +74 -132
  63. data/lib/tap/test/file_test_class.rb +4 -1
  64. data/lib/tap/test/regexp_escape.rb +2 -2
  65. data/lib/tap/test/script_test.rb +2 -2
  66. data/lib/tap/test/subset_test.rb +6 -6
  67. data/lib/tap/test/tap_test.rb +28 -154
  68. metadata +30 -51
  69. data/bin/rap +0 -118
  70. data/cgi/run.rb +0 -97
  71. data/lib/tap/declarations.rb +0 -229
  72. data/lib/tap/generator/generators/config/templates/doc.erb +0 -12
  73. data/lib/tap/generator/generators/config/templates/nodoc.erb +0 -8
  74. data/lib/tap/generator/generators/file_task/file_task_generator.rb +0 -27
  75. data/lib/tap/generator/generators/file_task/templates/file.txt +0 -11
  76. data/lib/tap/generator/generators/file_task/templates/result.yml +0 -6
  77. data/lib/tap/generator/generators/file_task/templates/task.erb +0 -33
  78. data/lib/tap/generator/generators/file_task/templates/test.erb +0 -29
  79. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +0 -5
  80. data/lib/tap/patches/optparse/summarize.rb +0 -62
  81. data/lib/tap/support/assignments.rb +0 -173
  82. data/lib/tap/support/class_configuration.rb +0 -182
  83. data/lib/tap/support/combinator.rb +0 -125
  84. data/lib/tap/support/configurable.rb +0 -113
  85. data/lib/tap/support/configurable_class.rb +0 -271
  86. data/lib/tap/support/configuration.rb +0 -170
  87. data/lib/tap/support/gems/rake.rb +0 -111
  88. data/lib/tap/support/instance_configuration.rb +0 -173
  89. data/lib/tap/support/joins/fork.rb +0 -19
  90. data/lib/tap/support/joins/merge.rb +0 -22
  91. data/lib/tap/support/joins/sequence.rb +0 -21
  92. data/lib/tap/support/lazy_attributes.rb +0 -45
  93. data/lib/tap/support/lazydoc.rb +0 -386
  94. data/lib/tap/support/lazydoc/comment.rb +0 -503
  95. data/lib/tap/support/lazydoc/config.rb +0 -17
  96. data/lib/tap/support/lazydoc/definition.rb +0 -36
  97. data/lib/tap/support/lazydoc/document.rb +0 -152
  98. data/lib/tap/support/lazydoc/method.rb +0 -24
  99. data/lib/tap/support/tdoc.rb +0 -409
  100. data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -38
  101. data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -42
  102. data/lib/tap/support/validation.rb +0 -479
  103. data/lib/tap/tasks/rake.rb +0 -57
@@ -1,38 +0,0 @@
1
- require 'rdoc/generators/html_generator'
2
-
3
- # Defines a specialized generator so it can be called for using a --fmt option.
4
- class TDocHTMLGenerator < Generators::HTMLGenerator # :nodoc:
5
- end
6
-
7
- module Generators # :nodoc:
8
- const_set(:RubyToken, RDoc::RubyToken)
9
-
10
- class HtmlClass < ContextUser # :nodoc:
11
- alias tdoc_original_value_hash value_hash
12
-
13
- def value_hash
14
- # split attributes into configurations and regular attributes
15
- configurations, attributes = @context.attributes.partition do |attribute|
16
- attribute.kind_of?(Tap::Support::TDoc::ConfigAttr)
17
- end
18
-
19
- # set the context attributes to JUST the regular
20
- # attributes and process as usual.
21
- @context.attributes.clear.concat attributes
22
- values = tdoc_original_value_hash
23
-
24
- # set the context attributes to the configurations
25
- # and echo the regular processing to produce a list
26
- # of configurations
27
- @context.attributes.clear.concat configurations
28
- @context.sections.each_with_index do |section, i|
29
- secdata = values["sections"][i]
30
-
31
- al = build_attribute_list(section)
32
- secdata["configurations"] = al unless al.empty?
33
- end
34
-
35
- values
36
- end
37
- end
38
- end
@@ -1,42 +0,0 @@
1
- require 'rdoc/generators/template/html/html'
2
-
3
- #
4
- # Add a template for documenting configurations. Do so by inserting in the
5
- # template into the content regions used to template html.
6
- # (see 'rdoc/generators/html_generator' line 864)
7
- #
8
- [
9
- RDoc::Page::BODY,
10
- RDoc::Page::FILE_PAGE,
11
- RDoc::Page::METHOD_LIST].each do |content|
12
-
13
- # this substitution method duplicates the attribute template for configurations
14
- # (see rdoc\generators\template\html line 523)
15
- #
16
- #IF:attributes
17
- # <div id="attribute-list">
18
- # <h3 class="section-bar">Attributes</h3>
19
- #
20
- # <div class="name-list">
21
- # <table>
22
- #START:attributes
23
- # <tr class="top-aligned-row context-row">
24
- # <td class="context-item-name">%name%</td>
25
- #IF:rw
26
- # <td class="context-item-value">&nbsp;[%rw%]&nbsp;</td>
27
- #ENDIF:rw
28
- #IFNOT:rw
29
- # <td class="context-item-value">&nbsp;&nbsp;</td>
30
- #ENDIF:rw
31
- # <td class="context-item-desc">%a_desc%</td>
32
- # </tr>
33
- #END:attributes
34
- # </table>
35
- # </div>
36
- # </div>
37
- #ENDIF:attributes
38
- #
39
- content.gsub!(/IF:attributes.*?ENDIF:attributes/m) do |match|
40
- match + "\n\n" + match.gsub(/attributes/, 'configurations').gsub(/Attributes/, 'Configurations')
41
- end
42
- end
@@ -1,479 +0,0 @@
1
- autoload(:PP, 'pp')
2
-
3
- module Tap
4
- module Support
5
-
6
- # Validation generates blocks for common validations and transformations of
7
- # configurations set through Configurable. In general these blocks load
8
- # string inputs as YAML and valdiate the results; non-string inputs are
9
- # simply validated.
10
- #
11
- # integer = Validation.integer
12
- # integer.class # => Proc
13
- # integer.call(1) # => 1
14
- # integer.call('1') # => 1
15
- # integer.call(nil) # => ValidationError
16
- #
17
- #--
18
- # Note the unusual syntax for declaring constants that are blocks
19
- # defined by lambda... ex:
20
- #
21
- # block = lambda {}
22
- # CONST = block
23
- #
24
- # This syntax plays well with RDoc, which otherwise gets jacked
25
- # when you do it all in one step.
26
- module Validation
27
-
28
- # Raised when Validation blocks fail.
29
- class ValidationError < ArgumentError
30
- def initialize(input, validations)
31
- super case
32
- when validations.empty?
33
- "no validations specified"
34
- else
35
- validation_str = PP.singleline_pp(validations, "")
36
- PP.singleline_pp(input, "expected #{validation_str} but was: ")
37
- end
38
- end
39
- end
40
-
41
- # Raised when yamlization fails.
42
- class YamlizationError < ArgumentError
43
- def initialize(input, error)
44
- super "#{error} ('#{input}')"
45
- end
46
- end
47
-
48
- module_function
49
-
50
- # Yaml conversion and checker. Valid if any of the validations
51
- # match in a case statement. Otherwise raises an error.
52
-
53
- # Returns input if any of the validations match any of the
54
- # inputs, as in a case statement. Raises a ValidationError
55
- # otherwise. For example:
56
- #
57
- # validate(10, [Integer, nil])
58
- #
59
- # Does the same as:
60
- #
61
- # case 10
62
- # when Integer, nil then input
63
- # else raise ValidationError.new(...)
64
- # end
65
- #
66
- # Note the validations input must be an Array or nil;
67
- # validate will raise an ArgumentError otherwise.
68
- # All inputs are considered VALID if validations == nil.
69
- def validate(input, validations)
70
- case validations
71
- when Array
72
-
73
- case input
74
- when *validations then input
75
- else raise ValidationError.new(input, validations)
76
- end
77
-
78
- when nil then input
79
- else raise ArgumentError.new("validations must be nil, or an array of valid inputs")
80
- end
81
- end
82
-
83
- # Attempts to load the input as YAML. Raises a YamlizationError
84
- # for errors.
85
- def yamlize(input)
86
- begin
87
- YAML.load(input)
88
- rescue
89
- raise YamlizationError.new(input, $!.message)
90
- end
91
- end
92
-
93
- # Returns a block that calls validate using the block input
94
- # and the input validations. Raises an error if no validations
95
- # are specified.
96
- def check(*validations)
97
- raise ArgumentError.new("no validations specified") if validations.empty?
98
- lambda {|input| validate(input, validations) }
99
- end
100
-
101
- # Returns a block that loads input strings as YAML, then
102
- # calls validate with the result and the input validations.
103
- # Non-string inputs are not converted.
104
- #
105
- # b = yaml(Integer, nil)
106
- # b.class # => Proc
107
- # b.call(1) # => 1
108
- # b.call("1") # => 1
109
- # b.call(nil) # => nil
110
- # b.call("str") # => ValidationError
111
- #
112
- # If no validations are specified, the result will be
113
- # returned without validation.
114
- def yaml(*validations)
115
- lambda do |input|
116
- res = input.kind_of?(String) ? yamlize(input) : input
117
- validations.empty? ? res : validate(res, validations)
118
- end
119
- end
120
-
121
- # Returns a block loads a String input as YAML then
122
- # validates the result is valid using the input
123
- # validations. If the input is not a String, the
124
- # input is validated directly.
125
- def yamlize_and_check(*validations)
126
- lambda do |input|
127
- input = yamlize(input) if input.kind_of?(String)
128
- validate(input, validations)
129
- end
130
- end
131
-
132
- # Returns a block that checks the input is a string.
133
- # Moreover, strings are re-evaluated as string
134
- # literals using %Q.
135
- #
136
- # string.class # => Proc
137
- # string.call('str') # => 'str'
138
- # string.call('\n') # => "\n"
139
- # string.call("\n") # => "\n"
140
- # string.call("%s") # => "%s"
141
- # string.call(nil) # => ValidationError
142
- # string.call(:sym) # => ValidationError
143
- #
144
- def string(); STRING; end
145
- string_validation_block = lambda do |input|
146
- input = validate(input, [String])
147
- eval %Q{"#{input}"}
148
- end
149
- STRING = string_validation_block
150
-
151
- # Same as string but allows nil. Note the special
152
- # behavior of the nil string '~' -- rather than
153
- # being treated as a string, it is processed as nil
154
- # to be consistent with the other [class]_or_nil
155
- # methods.
156
- #
157
- # string_or_nil.call('~') # => nil
158
- # string_or_nil.call(nil) # => nil
159
- def string_or_nil(); STRING_OR_NIL; end
160
- string_or_nil_validation_block = lambda do |input|
161
- input = validate(input, [String, nil])
162
- case input
163
- when nil, '~' then nil
164
- else eval %Q{"#{input}"}
165
- end
166
- end
167
- STRING_OR_NIL = string_or_nil_validation_block
168
-
169
- # Returns a block that checks the input is a symbol.
170
- # String inputs are loaded as yaml first.
171
- #
172
- # symbol.class # => Proc
173
- # symbol.call(:sym) # => :sym
174
- # symbol.call(':sym') # => :sym
175
- # symbol.call(nil) # => ValidationError
176
- # symbol.call('str') # => ValidationError
177
- #
178
- def symbol(); SYMBOL; end
179
- SYMBOL = yamlize_and_check(Symbol)
180
-
181
- # Same as symbol but allows nil:
182
- #
183
- # symbol_or_nil.call('~') # => nil
184
- # symbol_or_nil.call(nil) # => nil
185
- def symbol_or_nil(); SYMBOL_OR_NIL; end
186
- SYMBOL_OR_NIL = yamlize_and_check(Symbol, nil)
187
-
188
- # Returns a block that checks the input is true, false or nil.
189
- # String inputs are loaded as yaml first.
190
- #
191
- # boolean.class # => Proc
192
- # boolean.call(true) # => true
193
- # boolean.call(false) # => false
194
- # boolean.call(nil) # => nil
195
- #
196
- # boolean.call('true') # => true
197
- # boolean.call('yes') # => true
198
- # boolean.call('FALSE') # => false
199
- #
200
- # boolean.call(1) # => ValidationError
201
- # boolean.call("str") # => ValidationError
202
- #
203
- def boolean(); BOOLEAN; end
204
- BOOLEAN = yamlize_and_check(true, false, nil)
205
-
206
- # Same as boolean.
207
- def switch(); SWITCH; end
208
- SWITCH = yamlize_and_check(true, false, nil)
209
-
210
- # Same as boolean.
211
- def flag(); FLAG; end
212
- FLAG = yamlize_and_check(true, false, nil)
213
-
214
- # Returns a block that checks the input is an array.
215
- # String inputs are loaded as yaml first.
216
- #
217
- # array.class # => Proc
218
- # array.call([1,2,3]) # => [1,2,3]
219
- # array.call('[1, 2, 3]') # => [1,2,3]
220
- # array.call(nil) # => ValidationError
221
- # array.call('str') # => ValidationError
222
- #
223
- def array(); ARRAY; end
224
- ARRAY = yamlize_and_check(Array)
225
-
226
- # Same as array but allows nil:
227
- #
228
- # array_or_nil.call('~') # => nil
229
- # array_or_nil.call(nil) # => nil
230
- def array_or_nil(); ARRAY_OR_NIL; end
231
- ARRAY_OR_NIL = yamlize_and_check(Array, nil)
232
-
233
- # Returns a block that checks the input is an array.
234
- # If the input is a string the string is split along
235
- # commas and each value yamlized into an array.
236
- #
237
- # list.class # => Proc
238
- # list.call([1,2,3]) # => [1,2,3]
239
- # list.call('1,2,3') # => [1,2,3]
240
- # list.call('str') # => ['str']
241
- # list.call(nil) # => ValidationError
242
- #
243
- def list(); LIST; end
244
- list_block = lambda do |input|
245
- if input.kind_of?(String)
246
- input = input.split(/,/).collect {|arg| yamlize(arg) }
247
- end
248
-
249
- validate(input, [Array])
250
- end
251
- LIST = list_block
252
-
253
- # Returns a block that checks the input is a hash.
254
- # String inputs are loaded as yaml first.
255
- #
256
- # hash.class # => Proc
257
- # hash.call({'key' => 'value'}) # => {'key' => 'value'}
258
- # hash.call('key: value') # => {'key' => 'value'}
259
- # hash.call(nil) # => ValidationError
260
- # hash.call('str') # => ValidationError
261
- #
262
- def hash(); HASH; end
263
- HASH = yamlize_and_check(Hash)
264
-
265
- # Same as hash but allows nil:
266
- #
267
- # hash_or_nil.call('~') # => nil
268
- # hash_or_nil.call(nil) # => nil
269
- def hash_or_nil(); HASH_OR_NIL; end
270
- HASH_OR_NIL = yamlize_and_check(Hash, nil)
271
-
272
- # Returns a block that checks the input is an integer.
273
- # String inputs are loaded as yaml first.
274
- #
275
- # integer.class # => Proc
276
- # integer.call(1) # => 1
277
- # integer.call('1') # => 1
278
- # integer.call(1.1) # => ValidationError
279
- # integer.call(nil) # => ValidationError
280
- # integer.call('str') # => ValidationError
281
- #
282
- def integer(); INTEGER; end
283
- INTEGER = yamlize_and_check(Integer)
284
-
285
- # Same as integer but allows nil:
286
- #
287
- # integer_or_nil.call('~') # => nil
288
- # integer_or_nil.call(nil) # => nil
289
- def integer_or_nil(); INTEGER_OR_NIL; end
290
- INTEGER_OR_NIL = yamlize_and_check(Integer, nil)
291
-
292
- # Returns a block that checks the input is a float.
293
- # String inputs are loaded as yaml first.
294
- #
295
- # float.class # => Proc
296
- # float.call(1.1) # => 1.1
297
- # float.call('1.1') # => 1.1
298
- # float.call('1.0e+6') # => 1e6
299
- # float.call(1) # => ValidationError
300
- # float.call(nil) # => ValidationError
301
- # float.call('str') # => ValidationError
302
- #
303
- def float(); FLOAT; end
304
- FLOAT = yamlize_and_check(Float)
305
-
306
- # Same as float but allows nil:
307
- #
308
- # float_or_nil.call('~') # => nil
309
- # float_or_nil.call(nil) # => nil
310
- def float_or_nil(); FLOAT_OR_NIL; end
311
- FLOAT_OR_NIL = yamlize_and_check(Float, nil)
312
-
313
- # Returns a block that checks the input is a number.
314
- # String inputs are loaded as yaml first.
315
- #
316
- # num.class # => Proc
317
- # num.call(1.1) # => 1.1
318
- # num.call(1) # => 1
319
- # num.call(1e6) # => 1e6
320
- # num.call('1.1') # => 1.1
321
- # num.call('1.0e+6') # => 1e6
322
- # num.call(nil) # => ValidationError
323
- # num.call('str') # => ValidationError
324
- #
325
- def num(); NUMERIC; end
326
- NUMERIC = yamlize_and_check(Numeric)
327
-
328
- # Same as num but allows nil:
329
- #
330
- # num_or_nil.call('~') # => nil
331
- # num_or_nil.call(nil) # => nil
332
- def num_or_nil(); NUMERIC_OR_NIL; end
333
- NUMERIC_OR_NIL = yamlize_and_check(Numeric, nil)
334
-
335
- # Returns a block that checks the input is a regexp.
336
- # String inputs are converted to regexps using
337
- # Regexp#new.
338
- #
339
- # regexp.class # => Proc
340
- # regexp.call(/regexp/) # => /regexp/
341
- # regexp.call('regexp') # => /regexp/
342
- #
343
- # # use of ruby-specific flags can turn on/off
344
- # # features like case insensitive matching
345
- # regexp.call('(?i)regexp') # => /(?i)regexp/
346
- #
347
- def regexp(); REGEXP; end
348
- regexp_block = lambda do |input|
349
- input = Regexp.new(input) if input.kind_of?(String)
350
- validate(input, [Regexp])
351
- end
352
- REGEXP = regexp_block
353
-
354
- # Same as regexp but allows nil. Note the special
355
- # behavior of the nil string '~' -- rather than
356
- # being converted to a regexp, it is processed as
357
- # nil to be consistent with the other [class]_or_nil
358
- # methods.
359
- #
360
- # regexp_or_nil.call('~') # => nil
361
- # regexp_or_nil.call(nil) # => nil
362
- def regexp_or_nil(); REGEXP_OR_NIL; end
363
- regexp_or_nil_block = lambda do |input|
364
- input = case input
365
- when nil, '~' then nil
366
- when String then Regexp.new(input)
367
- else input
368
- end
369
-
370
- validate(input, [Regexp, nil])
371
- end
372
- REGEXP_OR_NIL = regexp_or_nil_block
373
-
374
- # Returns a block that checks the input is a range.
375
- # String inputs are split into a beginning and
376
- # end if possible, where each part is loaded as
377
- # yaml before being used to construct a Range.a
378
- #
379
- # range.class # => Proc
380
- # range.call(1..10) # => 1..10
381
- # range.call('1..10') # => 1..10
382
- # range.call('a..z') # => 'a'..'z'
383
- # range.call('-10...10') # => -10...10
384
- # range.call(nil) # => ValidationError
385
- # range.call('1.10') # => ValidationError
386
- # range.call('a....z') # => ValidationError
387
- #
388
- def range(); RANGE; end
389
- range_block = lambda do |input|
390
- if input.kind_of?(String) && input =~ /^([^.]+)(\.{2,3})([^.]+)$/
391
- input = Range.new(yamlize($1), yamlize($3), $2.length == 3)
392
- end
393
- validate(input, [Range])
394
- end
395
- RANGE = range_block
396
-
397
- # Same as range but allows nil:
398
- #
399
- # range_or_nil.call('~') # => nil
400
- # range_or_nil.call(nil) # => nil
401
- def range_or_nil(); RANGE_OR_NIL; end
402
- range_or_nil_block = lambda do |input|
403
- input = case input
404
- when nil, '~' then nil
405
- when String
406
- if input =~ /^([^.]+)(\.{2,3})([^.]+)$/
407
- Range.new(yamlize($1), yamlize($3), $2.length == 3)
408
- else
409
- input
410
- end
411
- else input
412
- end
413
-
414
- validate(input, [Range, nil])
415
- end
416
- RANGE_OR_NIL = range_or_nil_block
417
-
418
- # Returns a block that checks the input is a Time. String inputs are
419
- # loaded using Time.parse and then converted into times. Parsed times
420
- # are local unless specified otherwise.
421
- #
422
- # time.class # => Proc
423
- #
424
- # now = Time.now
425
- # time.call(now) # => now
426
- #
427
- # time.call('2008-08-08 20:00:00.00 +08:00').getutc.strftime('%Y/%m/%d %H:%M:%S')
428
- # # => '2008/08/08 12:00:00'
429
- #
430
- # time.call('2008-08-08').strftime('%Y/%m/%d %H:%M:%S')
431
- # # => '2008/08/08 00:00:00'
432
- #
433
- # time.call(1) # => ValidationError
434
- # time.call(nil) # => ValidationError
435
- #
436
- # Warning: Time.parse will parse a valid time (Time.now)
437
- # even when no time is specified:
438
- #
439
- # time.call('str').strftime('%Y/%m/%d %H:%M:%S')
440
- # # => Time.now.strftime('%Y/%m/%d %H:%M:%S')
441
- #
442
- def time()
443
- # adding this here is a compromise to lazy-load the parse
444
- # method (autoload doesn't work since Time already exists)
445
- require 'time' unless Time.respond_to?(:parse)
446
- TIME
447
- end
448
-
449
- time_block = lambda do |input|
450
- input = Time.parse(input) if input.kind_of?(String)
451
- validate(input, [Time])
452
- end
453
- TIME = time_block
454
-
455
- # Same as time but allows nil:
456
- #
457
- # time_or_nil.call('~') # => nil
458
- # time_or_nil.call(nil) # => nil
459
- def time_or_nil()
460
- # adding this check is a compromise to autoload the parse
461
- # method (autoload doesn't work since Time already exists)
462
- require 'time' unless Time.respond_to?(:parse)
463
- TIME_OR_NIL
464
- end
465
-
466
- time_or_nil_block = lambda do |input|
467
- input = case input
468
- when nil, '~' then nil
469
- when String then Time.parse(input)
470
- else input
471
- end
472
-
473
- validate(input, [Time, nil])
474
- end
475
- TIME_OR_NIL = time_or_nil_block
476
-
477
- end
478
- end
479
- end