validates_timeliness 3.0.0.beta.4 → 3.0.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{validates_timeliness}
5
- s.version = "3.0.0.beta.4"
5
+ s.version = "3.0.0.beta.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Adam Meehan"]
9
- s.date = %q{2010-09-29}
9
+ s.date = %q{2010-10-14}
10
10
  s.description = %q{Date and time validation plugin for Rails which allows custom formats}
11
11
  s.email = %q{adam.meehan@gmail.com}
12
12
  s.extra_rdoc_files = ["README.rdoc", "LICENSE", "CHANGELOG"]
13
- s.files = ["validates_timeliness.gemspec", "LICENSE", "CHANGELOG", "README.rdoc", "Rakefile", "lib/generators", "lib/generators/validates_timeliness", "lib/generators/validates_timeliness/install_generator.rb", "lib/generators/validates_timeliness/templates", "lib/generators/validates_timeliness/templates/en.yml", "lib/generators/validates_timeliness/templates/validates_timeliness.rb", "lib/validates_timeliness", "lib/validates_timeliness/attribute_methods.rb", "lib/validates_timeliness/conversion.rb", "lib/validates_timeliness/extensions", "lib/validates_timeliness/extensions/date_time_select.rb", "lib/validates_timeliness/extensions/multiparameter_handler.rb", "lib/validates_timeliness/extensions.rb", "lib/validates_timeliness/helper_methods.rb", "lib/validates_timeliness/orm", "lib/validates_timeliness/orm/active_record.rb", "lib/validates_timeliness/orm/mongoid.rb", "lib/validates_timeliness/parser.rb", "lib/validates_timeliness/validator.rb", "lib/validates_timeliness/version.rb", "lib/validates_timeliness.rb", "spec/model_helpers.rb", "spec/spec_helper.rb", "spec/test_model.rb", "spec/validates_timeliness", "spec/validates_timeliness/attribute_methods_spec.rb", "spec/validates_timeliness/conversion_spec.rb", "spec/validates_timeliness/extensions", "spec/validates_timeliness/extensions/date_time_select_spec.rb", "spec/validates_timeliness/extensions/multiparameter_handler_spec.rb", "spec/validates_timeliness/helper_methods_spec.rb", "spec/validates_timeliness/orm", "spec/validates_timeliness/orm/active_record_spec.rb", "spec/validates_timeliness/orm/mongoid_spec.rb", "spec/validates_timeliness/parser_spec.rb", "spec/validates_timeliness/validator", "spec/validates_timeliness/validator/after_spec.rb", "spec/validates_timeliness/validator/before_spec.rb", "spec/validates_timeliness/validator/is_at_spec.rb", "spec/validates_timeliness/validator/on_or_after_spec.rb", "spec/validates_timeliness/validator/on_or_before_spec.rb", "spec/validates_timeliness/validator_spec.rb"]
13
+ s.files = ["validates_timeliness.gemspec", "LICENSE", "CHANGELOG", "README.rdoc", "Rakefile", "lib/generators", "lib/generators/validates_timeliness", "lib/generators/validates_timeliness/install_generator.rb", "lib/generators/validates_timeliness/templates", "lib/generators/validates_timeliness/templates/en.yml", "lib/generators/validates_timeliness/templates/validates_timeliness.rb", "lib/validates_timeliness", "lib/validates_timeliness/attribute_methods.rb", "lib/validates_timeliness/conversion.rb", "lib/validates_timeliness/extensions", "lib/validates_timeliness/extensions/date_time_select.rb", "lib/validates_timeliness/extensions/multiparameter_handler.rb", "lib/validates_timeliness/extensions.rb", "lib/validates_timeliness/helper_methods.rb", "lib/validates_timeliness/orm", "lib/validates_timeliness/orm/active_record.rb", "lib/validates_timeliness/orm/mongoid.rb", "lib/validates_timeliness/railtie.rb", "lib/validates_timeliness/validator.rb", "lib/validates_timeliness/version.rb", "lib/validates_timeliness.rb", "spec/model_helpers.rb", "spec/spec_helper.rb", "spec/test_model.rb", "spec/validates_timeliness", "spec/validates_timeliness/attribute_methods_spec.rb", "spec/validates_timeliness/conversion_spec.rb", "spec/validates_timeliness/extensions", "spec/validates_timeliness/extensions/date_time_select_spec.rb", "spec/validates_timeliness/extensions/multiparameter_handler_spec.rb", "spec/validates_timeliness/helper_methods_spec.rb", "spec/validates_timeliness/orm", "spec/validates_timeliness/orm/active_record_spec.rb", "spec/validates_timeliness/orm/mongoid_spec.rb", "spec/validates_timeliness/validator", "spec/validates_timeliness/validator/after_spec.rb", "spec/validates_timeliness/validator/before_spec.rb", "spec/validates_timeliness/validator/is_at_spec.rb", "spec/validates_timeliness/validator/on_or_after_spec.rb", "spec/validates_timeliness/validator/on_or_before_spec.rb", "spec/validates_timeliness/validator_spec.rb"]
14
14
  s.homepage = %q{http://github.com/adzap/validates_timeliness}
15
15
  s.require_paths = ["lib"]
16
16
  s.rubyforge_project = %q{validates_timeliness}
@@ -22,8 +22,11 @@ Gem::Specification.new do |s|
22
22
  s.specification_version = 3
23
23
 
24
24
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
25
+ s.add_runtime_dependency(%q<timeliness>, ["~> 0.1.1"])
25
26
  else
27
+ s.add_dependency(%q<timeliness>, ["~> 0.1.1"])
26
28
  end
27
29
  else
30
+ s.add_dependency(%q<timeliness>, ["~> 0.1.1"])
28
31
  end
29
32
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validates_timeliness
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196427
4
+ hash: 62196425
5
5
  prerelease: true
6
6
  segments:
7
7
  - 3
8
8
  - 0
9
9
  - 0
10
10
  - beta
11
- - 4
12
- version: 3.0.0.beta.4
11
+ - 5
12
+ version: 3.0.0.beta.5
13
13
  platform: ruby
14
14
  authors:
15
15
  - Adam Meehan
@@ -17,10 +17,25 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2010-09-29 00:00:00 +10:00
20
+ date: 2010-10-14 00:00:00 +11:00
21
21
  default_executable:
22
- dependencies: []
23
-
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: timeliness
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ~>
30
+ - !ruby/object:Gem::Version
31
+ hash: 25
32
+ segments:
33
+ - 0
34
+ - 1
35
+ - 1
36
+ version: 0.1.1
37
+ type: :runtime
38
+ version_requirements: *id001
24
39
  description: Date and time validation plugin for Rails which allows custom formats
25
40
  email: adam.meehan@gmail.com
26
41
  executables: []
@@ -48,7 +63,7 @@ files:
48
63
  - lib/validates_timeliness/helper_methods.rb
49
64
  - lib/validates_timeliness/orm/active_record.rb
50
65
  - lib/validates_timeliness/orm/mongoid.rb
51
- - lib/validates_timeliness/parser.rb
66
+ - lib/validates_timeliness/railtie.rb
52
67
  - lib/validates_timeliness/validator.rb
53
68
  - lib/validates_timeliness/version.rb
54
69
  - lib/validates_timeliness.rb
@@ -62,7 +77,6 @@ files:
62
77
  - spec/validates_timeliness/helper_methods_spec.rb
63
78
  - spec/validates_timeliness/orm/active_record_spec.rb
64
79
  - spec/validates_timeliness/orm/mongoid_spec.rb
65
- - spec/validates_timeliness/parser_spec.rb
66
80
  - spec/validates_timeliness/validator/after_spec.rb
67
81
  - spec/validates_timeliness/validator/before_spec.rb
68
82
  - spec/validates_timeliness/validator/is_at_spec.rb
@@ -1,404 +0,0 @@
1
- require 'date'
2
-
3
- module ValidatesTimeliness
4
-
5
- # A date and time parsing library which allows you to add custom formats using
6
- # simple predefined tokens. This makes it much easier to catalogue and customize
7
- # the formats rather than dealing directly with regular expressions.
8
- #
9
- # Formats can be added or removed to customize the set of valid date or time
10
- # string values.
11
- #
12
- class Parser
13
- cattr_reader :time_expressions, :date_expressions, :datetime_expressions
14
-
15
- # Set the threshold value for a two digit year to be considered last century
16
- #
17
- # Default: 30
18
- #
19
- # Example:
20
- # year = '29' is considered 2029
21
- # year = '30' is considered 1930
22
- #
23
- cattr_accessor :ambiguous_year_threshold
24
- self.ambiguous_year_threshold = 30
25
-
26
- # Format tokens:
27
- # y = year
28
- # m = month
29
- # d = day
30
- # h = hour
31
- # n = minute
32
- # s = second
33
- # u = micro-seconds
34
- # ampm = meridian (am or pm) with or without dots (e.g. am, a.m, or a.m.)
35
- # _ = optional space
36
- # tz = Timezone abbreviation (e.g. UTC, GMT, PST, EST)
37
- # zo = Timezone offset (e.g. +10:00, -08:00, +1000)
38
- #
39
- # All other characters are considered literal. You can embed regexp in the
40
- # format but no gurantees that it will remain intact. If you avoid the use
41
- # of any token characters and regexp dots or backslashes as special characters
42
- # in the regexp, it may well work as expected. For special characters use
43
- # POSIX character clsses for safety.
44
- #
45
- # Repeating tokens:
46
- # x = 1 or 2 digits for unit (e.g. 'h' means an hour can be '9' or '09')
47
- # xx = 2 digits exactly for unit (e.g. 'hh' means an hour can only be '09')
48
- #
49
- # Special Cases:
50
- # yy = 2 or 4 digit year
51
- # yyyy = exactly 4 digit year
52
- # mmm = month long name (e.g. 'Jul' or 'July')
53
- # ddd = Day name of 3 to 9 letters (e.g. Wed or Wednesday)
54
- # u = microseconds matches 1 to 6 digits
55
- #
56
- # Any other invalid combination of repeating tokens will be swallowed up
57
- # by the next lowest length valid repeating token (e.g. yyy will be
58
- # replaced with yy)
59
-
60
- cattr_accessor :time_formats
61
- @@time_formats = [
62
- 'hh:nn:ss',
63
- 'hh-nn-ss',
64
- 'h:nn',
65
- 'h.nn',
66
- 'h nn',
67
- 'h-nn',
68
- 'h:nn_ampm',
69
- 'h.nn_ampm',
70
- 'h nn_ampm',
71
- 'h-nn_ampm',
72
- 'h_ampm'
73
- ]
74
-
75
- cattr_accessor :date_formats
76
- @@date_formats = [
77
- 'yyyy-mm-dd',
78
- 'yyyy/mm/dd',
79
- 'yyyy.mm.dd',
80
- 'm/d/yy',
81
- 'd/m/yy',
82
- 'm\d\yy',
83
- 'd\m\yy',
84
- 'd-m-yy',
85
- 'dd-mm-yyyy',
86
- 'd.m.yy',
87
- 'd mmm yy'
88
- ]
89
-
90
- cattr_accessor :datetime_formats
91
- @@datetime_formats = [
92
- 'yyyy-mm-dd hh:nn:ss',
93
- 'yyyy-mm-dd h:nn',
94
- 'yyyy-mm-dd h:nn_ampm',
95
- 'yyyy-mm-dd hh:nn:ss.u',
96
- 'm/d/yy h:nn:ss',
97
- 'm/d/yy h:nn_ampm',
98
- 'm/d/yy h:nn',
99
- 'd/m/yy hh:nn:ss',
100
- 'd/m/yy h:nn_ampm',
101
- 'd/m/yy h:nn',
102
- 'dd-mm-yyyy hh:nn:ss',
103
- 'dd-mm-yyyy h:nn_ampm',
104
- 'dd-mm-yyyy h:nn',
105
- 'ddd, dd mmm yyyy hh:nn:ss (zo|tz)', # RFC 822
106
- 'ddd mmm d hh:nn:ss zo yyyy', # Ruby time string
107
- 'yyyy-mm-ddThh:nn:ssZ', # iso 8601 without zone offset
108
- 'yyyy-mm-ddThh:nn:sszo' # iso 8601 with zone offset
109
- ]
110
-
111
-
112
- # All tokens available for format construction. The token array is made of
113
- # validation regexp and key for format proc mapping if any.
114
- # If the token needs no format proc arg then the validation regexp should
115
- # not have a capturing group, as all captured groups are passed to the
116
- # format proc.
117
- #
118
- # The token regexp should only use a capture group if 'look-behind' anchor
119
- # is required. The first capture group will be considered a literal and put
120
- # into the validation regexp string as-is. This is a hack.
121
- #
122
- cattr_accessor :format_tokens
123
- @@format_tokens = {
124
- 'ddd' => [ '\w{3,9}' ],
125
- 'dd' => [ '\d{2}', :day ],
126
- 'd' => [ '\d{1,2}', :day ],
127
- 'mmm' => [ '\w{3,9}', :month ],
128
- 'mm' => [ '\d{2}', :month ],
129
- 'm' => [ '\d{1,2}', :month ],
130
- 'yyyy' => [ '\d{4}', :year ],
131
- 'yy' => [ '\d{4}|\d{2}', :year ],
132
- 'hh' => [ '\d{2}', :hour ],
133
- 'h' => [ '\d{1,2}', :hour ],
134
- 'nn' => [ '\d{2}', :min ],
135
- 'n' => [ '\d{1,2}', :min ],
136
- 'ss' => [ '\d{2}', :sec ],
137
- 's' => [ '\d{1,2}', :sec ],
138
- 'u' => [ '\d{1,6}', :usec ],
139
- 'ampm' => [ '[aApP]\.?[mM]\.?', :meridian ],
140
- 'zo' => [ '[+-]\d{2}:?\d{2}', :offset ],
141
- 'tz' => [ '[A-Z]{1,4}' ],
142
- '_' => [ '\s?' ]
143
- }
144
-
145
- # Arguments which will be passed to the format proc if matched in the
146
- # time string. The key must be the key from the format tokens. The array
147
- # consists of the arry position of the arg, the arg name, and the code to
148
- # place in the time array slot. The position can be nil which means the arg
149
- # won't be placed in the array.
150
- #
151
- # The code can be used to manipulate the arg value if required, otherwise
152
- # should just be the arg name.
153
- #
154
- cattr_accessor :format_proc_args
155
- @@format_proc_args = {
156
- :year => [0, 'y', 'unambiguous_year(y)'],
157
- :month => [1, 'm', 'month_index(m)'],
158
- :day => [2, 'd', 'd'],
159
- :hour => [3, 'h', 'full_hour(h, md ||= nil)'],
160
- :min => [4, 'n', 'n'],
161
- :sec => [5, 's', 's'],
162
- :usec => [6, 'u', 'microseconds(u)'],
163
- :offset => [7, 'z', 'offset_in_seconds(z)'],
164
- :meridian => [nil, 'md', nil]
165
- }
166
-
167
- @@type_wrapper = {
168
- :date => [/\A/, nil],
169
- :time => [nil , /\Z/],
170
- :datetime => [/\A/, /\Z/]
171
- }
172
-
173
- class << self
174
-
175
- def compile_format_expressions
176
- @@time_expressions = compile_formats(@@time_formats)
177
- @@date_expressions = compile_formats(@@date_formats)
178
- @@datetime_expressions = compile_formats(@@datetime_formats)
179
- end
180
-
181
- def parse(raw_value, type, options={})
182
- return nil if raw_value.blank?
183
- return raw_value if raw_value.acts_like?(:time) || raw_value.acts_like?(:date)
184
-
185
- time_array = _parse(raw_value, type, options.reverse_merge(:strict => true))
186
- return nil if time_array.nil?
187
-
188
- if type == :date
189
- Date.new(*time_array[0..2]) rescue nil
190
- else
191
- make_time(time_array[0..7], options[:timezone_aware])
192
- end
193
- end
194
-
195
- def make_time(time_array, timezone_aware=false)
196
- # Enforce strict date part validity which Time class does not
197
- return nil unless Date.valid_civil?(*time_array[0..2])
198
-
199
- if timezone_aware
200
- Time.zone.local(*time_array)
201
- else
202
- Time.time_with_datetime_fallback(ValidatesTimeliness.default_timezone, *time_array)
203
- end
204
- rescue ArgumentError, TypeError
205
- nil
206
- end
207
-
208
- # Loop through format expressions for type and call the format method on a match.
209
- # Allow pre or post match strings to exist if strict is false. Otherwise wrap
210
- # regexp in start and end anchors.
211
- #
212
- # Returns time array if matches a format, nil otherwise.
213
- #
214
- def _parse(string, type, options={})
215
- options.reverse_merge!(:strict => true)
216
-
217
- sets = if options[:format]
218
- options[:strict] = true
219
- [ send("#{type}_expressions").assoc(options[:format]) ]
220
- else
221
- expression_set(type, string)
222
- end
223
-
224
- set = sets.find do |format, regexp|
225
- string =~ wrap_regexp(regexp, type, options[:strict])
226
- end
227
-
228
- if set
229
- last = options[:include_offset] ? 8 : 7
230
- values = send(:"format_#{set[0]}", *$~[1..last])
231
- values[0..2] = ValidatesTimeliness.dummy_date_for_time_type if type == :time
232
- return values
233
- end
234
- rescue
235
- nil
236
- end
237
-
238
- # Delete formats of specified type. Error raised if format not found.
239
- def remove_formats(type, *remove_formats)
240
- remove_formats.each do |format|
241
- unless self.send("#{type}_formats").delete(format)
242
- raise "Format #{format} not found in #{type} formats"
243
- end
244
- end
245
- compile_format_expressions
246
- end
247
-
248
- # Adds new formats. Must specify format type and can specify a :before
249
- # option to nominate which format the new formats should be inserted in
250
- # front on to take higher precedence.
251
- # Error is raised if format already exists or if :before format is not found.
252
- def add_formats(type, *add_formats)
253
- formats = self.send("#{type}_formats")
254
- options = {}
255
- options = add_formats.pop if add_formats.last.is_a?(Hash)
256
- before = options[:before]
257
- raise "Format for :before option #{format} was not found." if before && !formats.include?(before)
258
-
259
- add_formats.each do |format|
260
- raise "Format #{format} is already included in #{type} formats" if formats.include?(format)
261
-
262
- index = before ? formats.index(before) : -1
263
- formats.insert(index, format)
264
- end
265
- compile_format_expressions
266
- end
267
-
268
- # Removes formats where the 1 or 2 digit month comes first, to eliminate
269
- # formats which are ambiguous with the European style of day then month.
270
- # The mmm token is ignored as its not ambigous.
271
- def remove_us_formats
272
- us_format_regexp = /\Am{1,2}[^m]/
273
- date_formats.reject! { |format| us_format_regexp =~ format }
274
- datetime_formats.reject! { |format| us_format_regexp =~ format }
275
- compile_format_expressions
276
- end
277
-
278
- def full_hour(hour, meridian)
279
- hour = hour.to_i
280
- return hour if meridian.nil?
281
- if meridian.delete('.').downcase == 'am'
282
- raise if hour == 0 || hour > 12
283
- hour == 12 ? 0 : hour
284
- else
285
- hour == 12 ? hour : hour + 12
286
- end
287
- end
288
-
289
- def unambiguous_year(year)
290
- if year.length <= 2
291
- century = Time.now.year.to_s[0..1].to_i
292
- century -= 1 if year.to_i >= ambiguous_year_threshold
293
- year = "#{century}#{year.rjust(2,'0')}"
294
- end
295
- year.to_i
296
- end
297
-
298
- def month_index(month)
299
- return month.to_i if month.to_i.nonzero?
300
- abbr_month_names.index(month.capitalize) || month_names.index(month.capitalize)
301
- end
302
-
303
- def month_names
304
- I18n.t('date.month_names')
305
- end
306
-
307
- def abbr_month_names
308
- I18n.t('date.abbr_month_names')
309
- end
310
-
311
- def microseconds(usec)
312
- (".#{usec}".to_f * 1_000_000).to_i
313
- end
314
-
315
- def offset_in_seconds(offset)
316
- sign = offset =~ /^-/ ? -1 : 1
317
- parts = offset.scan(/\d\d/).map {|p| p.to_f }
318
- parts[1] = parts[1].to_f / 60
319
- (parts[0] + parts[1]) * sign * 3600
320
- end
321
-
322
- private
323
-
324
- # Generate regular expression from format string
325
- def generate_format_expression(string_format)
326
- format = string_format.dup
327
- format.gsub!(/([\.\\])/, '\\\\\1') # escapes dots and backslashes
328
- found_tokens, token_order = [], []
329
-
330
- tokens = format_tokens.keys.sort {|a,b| a.size <=> b.size }.reverse
331
- tokens.each do |token|
332
- regexp_str, arg_key = *format_tokens[token]
333
- if format.gsub!(/#{token}/, "%<#{found_tokens.size}>")
334
- regexp_str = "(#{regexp_str})" if arg_key
335
- found_tokens << [regexp_str, arg_key]
336
- end
337
- end
338
-
339
- format.scan(/%<(\d)>/).each {|token_index|
340
- token_index = token_index.first
341
- token = found_tokens[token_index.to_i]
342
- format.gsub!("%<#{token_index}>", token[0])
343
- token_order << token[1]
344
- }
345
-
346
- compile_format_method(token_order.compact, string_format)
347
- Regexp.new(format)
348
- rescue
349
- raise "The following format regular expression failed to compile: #{format}\n from format #{string_format}."
350
- end
351
-
352
- # Compiles a format method which maps the regexp capture groups to method
353
- # arguments based on order captured. A time array is built using the values
354
- # in the position indicated by the first element of the proc arg array.
355
- #
356
- def compile_format_method(order, name)
357
- values = [nil] * 7
358
- args = []
359
- order.each do |part|
360
- proc_arg = format_proc_args[part]
361
- args << proc_arg[1]
362
- values[proc_arg[0]] = proc_arg[2] if proc_arg[0]
363
- end
364
- class_eval <<-DEF
365
- class << self
366
- define_method(:"format_#{name}") do |#{args.join(',')}|
367
- [#{values.map {|i| i || 'nil' }.join(',')}].map {|i| i.is_a?(Float) ? i : i.to_i }
368
- end
369
- end
370
- DEF
371
- end
372
-
373
- def compile_formats(formats)
374
- formats.map { |format| [ format, generate_format_expression(format) ] }
375
- end
376
-
377
- # Pick expression set and combine date and datetimes for
378
- # datetime attributes to allow date string as datetime
379
- def expression_set(type, string)
380
- case type
381
- when :date
382
- date_expressions
383
- when :time
384
- time_expressions
385
- when :datetime
386
- # gives a speed-up for date string as datetime attributes
387
- if string.length < 11
388
- date_expressions + datetime_expressions
389
- else
390
- datetime_expressions + date_expressions
391
- end
392
- end
393
- end
394
-
395
- def wrap_regexp(regexp, type, strict=false)
396
- type = strict ? :datetime : type
397
- /#{@@type_wrapper[type][0]}#{regexp}#{@@type_wrapper[type][1]}/
398
- end
399
-
400
- end
401
- end
402
- end
403
-
404
- ValidatesTimeliness::Parser.compile_format_expressions