Module CustomValidations
In: lib/custom_validations.rb

検証部品を実装するモジュール。

Methods

Included Modules

GetText::Rails

Classes and Modules

Module CustomValidations::SingletonValidateable
Module CustomValidations::Validateable

Public Instance methods

[Source]

     # File lib/custom_validations.rb, line 532
532:   def validates_earlier_date_of(*attr_names)
533:     configuration = {
534:       :message => ActiveRecord::Errors.default_error_messages[:earlier_date],
535:     }
536:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
537:     date = configuration.delete(:than)
538:     case date
539:     when String
540:       display_date = date.to_display_date
541:       enum = "" ... display_date
542:       proc = lambda {|value| enum.include?(value.to_display_date)}
543:     when Time
544:       display_date = date.strftime("%Y%m%d").to_display_date
545:       enum = Time.at(0) ... date
546:       proc = lambda {|value| enum.include?(value)}
547:     else
548:       raise ArgumentError, "Date unspecified. Specify the :than option."
549:     end
550:     # logic from validates_inclusion_of
551:     validates_each(attr_names, configuration) do |record, attr_name, value|
552:       record.errors.add(attr_name, _(configuration[:message]) % {:date => display_date}) unless proc.call(value)
553:     end
554:   end

[Source]

     # File lib/custom_validations.rb, line 314
314:   def validates_filtered_length_of(*attrs)
315:     options = {
316:       :too_long     => ActiveRecord::Errors.default_error_messages[:too_long],
317:       :too_short    => ActiveRecord::Errors.default_error_messages[:too_short],
318:       :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length]
319:     }.merge(::ActiveRecord::Validations::ClassMethods::DEFAULT_VALIDATION_OPTIONS)
320:     options.update(attrs.pop.symbolize_keys) if attrs.last.is_a?(Hash)
321: 
322:     ## add filter option
323:     filter = options[:filter]
324:     unless filter.respond_to?(:call)
325:       raise ArgumentError, "Filter unspecified. Specify the :filter option."
326:     end
327: 
328:     # Ensure that one and only one range option is specified.
329:     range_options = ::ActiveRecord::Validations::ClassMethods::ALL_RANGE_OPTIONS & options.keys
330:     case range_options.size
331:     when 0
332:       raise ArgumentError, 'Range unspecified.  Specify the :within, :maximum, :minimum, or :is option.'
333:     when 1
334:       # Valid number of options; do nothing.
335:     else
336:       raise ArgumentError, 'Too many range options specified.  Choose only one.'
337:     end
338: 
339:     # Get range option and value.
340:     option = range_options.first
341:     option_value = options[range_options.first]
342: 
343:     case option
344:     when :within, :in
345:       raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range)
346: 
347:       too_short = options[:too_short] % option_value.begin
348:       too_long  = options[:too_long]  % option_value.end
349: 
350:       validates_each(attrs, options) do |record, attr, value|
351:         ## change from "value.split(//).size" in validates_length_of
352:         ## to "filter.call(value)".
353:         if value.nil? or filter.call(value) < option_value.begin
354:           record.errors.add(attr, too_short)
355:         elsif filter.call(value) > option_value.end
356:           record.errors.add(attr, too_long)
357:         end
358:       end
359:     when :is, :minimum, :maximum
360:       raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0
361: 
362:       # Declare different validations per option.
363:       validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" }
364:       message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }
365: 
366:       message = (options[:message] || options[message_options[option]]) % option_value
367: 
368:       validates_each(attrs, options) do |record, attr, value|
369:         ## change from "value.split(//).size" or "value.size" in validates_length_of
370:         ## to "filter.call(value)".
371:         begin
372:           unless !value.nil? and filter.call(Integer(value)).method(validity_checks[option])[option_value]
373:             record.errors.add(attr, message)
374:           end
375:         rescue ArgumentError
376:           record.errors.add(attr, message)
377:         end
378:       end
379:     end
380:   end

[Source]

     # File lib/custom_validations.rb, line 178
178:   def validates_float_of(*attr_names)
179:     configuration = {
180:       :message => ActiveRecord::Errors.default_error_messages[:not_float],
181:       :allow_nil => false,
182:       :non_negative => false,
183:     }
184:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
185: 
186:     configuration[:with] = configuration[:non_negative] ? /\A\+?[0-9]+\.[0-9]+\z/ : /\A[+-]?[0-9]+\.[0-9]+\z/
187:     attr_names.push configuration
188:     validates_format_before_type_cast_of(*attr_names)
189:   end

[Source]

     # File lib/custom_validations.rb, line 400
400:   def validates_fractional_length_of(*attr_names)
401:     configuration = {
402:       :too_long     => ActiveRecord::Errors.default_error_messages[:too_long_fractional],
403:       :too_short    => ActiveRecord::Errors.default_error_messages[:too_short_fractional],
404:       :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length_fractional],
405:     }
406:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
407:     configuration[:filter] = proc do |value|
408:       if /\.([0-9]*)(?![0-9])/ =~ value.to_s
409:         $1.length
410:       else
411:         0
412:       end
413:     end
414:     attr_names.push configuration
415:     validates_filtered_length_of(*attr_names)
416:   end

[Source]

     # File lib/custom_validations.rb, line 255
255:   def validates_fullwidth_of(*attr_names)
256:     configuration = {
257:       :message => ActiveRecord::Errors.default_error_messages[:not_fullwidth_chars],
258:       :invalid_sequence_message => ActiveRecord::Errors.default_error_messages[:invalid_sequence],
259:       :blank_message => ActiveRecord::Errors.default_error_messages[:not_fullwidth_chars],
260:       :on => :save,
261:       :allow_nil => false,
262:     }
263:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
264: 
265:     unless configuration[:allow_nil]
266:       # use validates_each instead of validates_presence_of because gettextize
267:       validates_each(attr_names, configuration) do |record, attr_name, value|
268:         if value.blank?
269:           record.errors.add attr_name, _(configuration[:blank_message])
270:         end
271:       end
272:     end
273: 
274:     validates_each(attr_names, configuration) do |record, attr_name, value|
275:       begin
276:         cp932_string = Iconv.conv("cp932", "utf-8", value.to_s)
277:         scanner, char = StringScanner.new(cp932_string), /./s
278:         while c = scanner.scan(char)
279:           if c.length != 2
280:             record.errors.add attr_name, _(configuration[:message])
281:             break
282:           end
283:         end
284:       rescue Iconv::IllegalSequence
285:         record.errors.add attr_name, _(configuration[:invalid_sequence])
286:       end
287:     end
288:   end

[Source]

     # File lib/custom_validations.rb, line 290
290:   def validates_inclusion_chars_of(*attr_names)
291:     configuration = {
292:       :message => ActiveRecord::Errors.default_error_messages[:not_inclusion_chars],
293:       :on => :save,
294:       :allow_nil => false,
295:     }
296:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
297: 
298:     chars = configuration[:chars]
299:     raise(ArgumentError, "Characters must be supplied as the :chars option of the configuration hash") if chars.blank?
300: 
301:     if chars.is_a?(Array)
302:       chars = chars.join("")
303:     end
304:     chars = Regexp.escape(chars)
305:     configuration[:with] = /\A[#{chars}]+\z/
306: 
307:     validates_each(attr_names, configuration) do |record, attr_name, value|
308:       unless record.send("#{attr_name}_before_type_cast").to_s =~ configuration[:with]
309:         record.errors.add(attr_name, _(configuration[:message]) % {:chars => chars})
310:       end
311:     end
312:   end

[Source]

     # File lib/custom_validations.rb, line 156
156:   def validates_integer_of(*attr_names)
157:     configuration = {
158:       :message => ActiveRecord::Errors.default_error_messages[:not_integer],
159:       :allow_nil => false,
160:       :non_negative => false,
161:     }
162:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
163:     configuration[:with] = configuration[:non_negative] ? /\A\+?\d+\z/ : /\A[+-]?\d+\z/
164:     attr_names.push configuration
165:     validates_format_before_type_cast_of(*attr_names)
166:   end

[Source]

     # File lib/custom_validations.rb, line 382
382:   def validates_integral_length_of(*attr_names)
383:     configuration = {
384:       :too_long     => ActiveRecord::Errors.default_error_messages[:too_long_integer],
385:       :too_short    => ActiveRecord::Errors.default_error_messages[:too_short_integer],
386:       :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length_integer],
387:     }
388:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
389:     configuration[:filter] = proc do |value|
390:       if /\A[+-]?([0-9]*)(?![0-9])/ =~ value.to_s
391:         $1.length
392:       else
393:         0
394:       end
395:     end
396:     attr_names.push configuration
397:     validates_filtered_length_of(*attr_names)
398:   end

[Source]

     # File lib/custom_validations.rb, line 508
508:   def validates_later_date_of(*attr_names)
509:     configuration = {
510:       :message => ActiveRecord::Errors.default_error_messages[:later_date],
511:     }
512:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
513:     date = configuration.delete(:than)
514:     case date
515:     when String
516:       display_date = date.to_display_date
517:       enum = "" .. display_date
518:       proc = lambda {|value| enum.include?(value.to_display_date)}
519:     when Time
520:       display_date = date.strftime("%Y%m%d").to_display_date
521:       enum = Time.at(0) .. date
522:       proc = lambda {|value| enum.include?(value)}
523:     else
524:       raise ArgumentError, "Date unspecified. Specify the :than option."
525:     end
526:     # logic from validates_exclusion_of
527:     validates_each(attr_names, configuration) do |record, attr_name, value|
528:       record.errors.add(attr_name, _(configuration[:message]) % {:date => display_date}) if proc.call(value)
529:     end
530:   end

[Source]

     # File lib/custom_validations.rb, line 476
476:   def validates_minimum_number_of(*attr_names)
477:     configuration = {
478:       :too_long     => ActiveRecord::Errors.default_error_messages[:too_large],
479:       :too_short    => ActiveRecord::Errors.default_error_messages[:too_small],
480:       :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_number],
481:     }
482:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
483:     configuration[:filter] = proc {|value| value }
484:     attr_names.push configuration
485:     validates_filtered_length_of(*attr_names)
486:   end

[Source]

     # File lib/custom_validations.rb, line 168
168:   def validates_non_negative_float_of(*attr_names)
169:     configuration = {
170:       :message => ActiveRecord::Errors.default_error_messages[:negative_float],
171:       :non_negative => true,
172:     }
173:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
174:     attr_names.push configuration
175:     validates_float_of(*attr_names)
176:   end

[Source]

     # File lib/custom_validations.rb, line 146
146:   def validates_non_negative_integer_of(*attr_names)
147:     configuration = {
148:       :message => ActiveRecord::Errors.default_error_messages[:negative_integer],
149:       :non_negative => true,
150:     }
151:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
152:     attr_names.push configuration
153:     validates_integer_of(*attr_names)
154:   end

[Source]

     # File lib/custom_validations.rb, line 201
201:   def validates_nonzero_of(*attr_names)
202:     configuration = {
203:       :message => ActiveRecord::Errors.default_error_messages[:nonzero],
204:     }
205:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
206: 
207:     validates_each(attr_names, configuration) do |record, attr_name, value|
208:       unless value.to_f.nonzero?
209:         record.errors.add(attr_name, configuration[:message])
210:       end
211:     end
212:   end

[Source]

     # File lib/custom_validations.rb, line 488
488:   def validates_period_of(*attr_names)
489:     configuration = {
490:       :message => ActiveRecord::Errors.default_error_messages[:period],
491:     }
492:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
493:     if e = configuration.delete(:in)
494:       enum = (e.first.to_display_date .. e.last.to_display_date)
495:       proc = lambda {|value| enum.include?(value.to_display_date)}
496:     elsif min = configuration.delete(:minimum)
497:       proc = lambda {|value| min.to_display_date <= value.to_display_date}
498:     elsif max = configuration.delete(:maximum)
499:       proc = lambda {|value| value.to_display_date <= max.to_display_date}
500:     else
501:       raise ArgumentError, "no option of the configuration hash"
502:     end
503:     validates_each(attr_names, configuration) do |record, attr_name, value|
504:       record.errors.add(attr_name, configuration[:message]) unless proc.call(value)
505:     end
506:   end

[Source]

     # File lib/custom_validations.rb, line 556
556:   def validates_row_of(*attr_names)
557:     configuration = {
558:       :message => ActiveRecord::Errors.default_error_messages[:row],
559:     }
560:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
561: 
562:     model_class_name = configuration[:table].classify
563:     model_class = model_class_name.constantize
564:     column_name = configuration[:column]
565:     find_by = "find_by_#{column_name}"
566: 
567:     validates_each(attr_names, configuration) do |record, attr_name, value|
568:       if model_class.__send__(find_by, value, :select => "id").nil?
569:         message = _(configuration[:message]) % {
570:           :column => model_class.human_attribute_name(column_name),
571:           :table => _(model_class_name), # FIXME
572:         }
573:         record.errors.add(attr_name, message)
574:       end
575:     end
576:   end

1〜9999年の範囲内の日付かどうかをチェックする。

[Source]

     # File lib/custom_validations.rb, line 454
454:   def validates_year_month_day_of(*attr_names)
455:     configuration = {
456:       :message => ActiveRecord::Errors.default_error_messages[:invalid_year_month_day],
457:     }
458:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
459: 
460:     validates_each(attr_names, configuration) do |record, attr_name, value|
461:       begin
462:         case value.to_s
463:         when /\A(\d{4})([\/\-]?)(\d{2})\2(\d{2})\z/, /\A(\d+)([\/\-])(\d+)\2(\d+)\z/
464:           year = $1.to_i
465:           raise ArgumentError unless (1..9999).include?(year)
466:           date = Date.new(year, $3.to_i, $4.to_i)
467:         else
468:           record.errors.add attr_name, configuration[:message]
469:         end
470:       rescue ArgumentError
471:         record.errors.add attr_name, configuration[:message]
472:       end
473:     end
474:   end

1〜9999年と1〜12月の範囲内かどうかをチェックする。

[Source]

     # File lib/custom_validations.rb, line 433
433:   def validates_year_month_of(*attr_names)
434:     configuration = {
435:       :message => ActiveRecord::Errors.default_error_messages[:invalid_year_month],
436:     }
437:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
438: 
439:     validates_each(attr_names, configuration) do |record, attr_name, value|
440:       valid = false
441:       case value.to_s
442:       when /\A(\d+)[\/\-](\d+)\z/, /\A(\d{4})(\d{2})\z/
443:         if (1..9999).include?($1.to_i) && (1..12).include?($2.to_i)
444:           valid = true
445:         end
446:       end
447:       unless valid
448:         record.errors.add attr_name, configuration[:message]
449:       end
450:     end
451:   end

1〜9999年の範囲内かどうかをチェックする。

[Source]

     # File lib/custom_validations.rb, line 419
419:   def validates_year_of(*attr_names)
420:     configuration = {
421:       :message => ActiveRecord::Errors.default_error_messages[:invalid_year],
422:     }
423:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
424: 
425:     validates_each(attr_names, configuration) do |record, attr_name, value|
426:       unless /\A\d+\z/ =~ value.to_s && (1..9999).include?(value.to_i)
427:         record.errors.add(attr_name, configuration[:message])
428:       end
429:     end
430:   end

[Source]

     # File lib/custom_validations.rb, line 191
191:   def validates_zero_of(*attr_names)
192:     configuration = {
193:       :message => ActiveRecord::Errors.default_error_messages[:not_zero],
194:       :with => /\A[+-]?0+(?:.0+)?\z/,
195:     }
196:     configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
197:     attr_names.push configuration
198:     validates_format_before_type_cast_of(*attr_names)
199:   end

[Validate]