| Module | CustomValidations |
| In: |
lib/custom_validations.rb
|
検証部品を実装するモジュール。
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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年の範囲内の日付かどうかをチェックする。
# 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月の範囲内かどうかをチェックする。
# 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年の範囲内かどうかをチェックする。
# 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
# 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