# Validations based on negations of regular expressions. # validates_not_format_of takes an array of attributes, # a regular expression to apply to them, # and an optional hash of configuration options. # # All other validations take an array of attributes, # a word or list of words to act upon, # and an optional hash of configuration options. # # Examples: # validates_does_have_the_words :username, :description, %w(chicken yellow coward), :ignore_case => true # In this case, the model will not be valid if the username or description attributes contain any of the # restricted words, regardless of case. # module ActiveRecord module Validations module ClassMethods # Negates a regular expression match against an attribute. # Similar to grep -v # def validates_not_format_of(*attr_names) configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save, :with => nil } configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) raise(ArgumentError, "A regular expression must be supplied as the :with option of the configuration hash") unless configuration[:with].is_a?(Regexp) validates_each(attr_names, configuration) do |record, attr_name, value| record.errors.add(attr_name, configuration[:message]) if value.to_s =~ configuration[:with] end end def validates_does_not_begin_with_the_word(*attr_names) validates_attributes_not_format_of_block(attr_names) { |word| "^#{word}" } end alias :validates_does_not_begin_with_the_words :validates_does_not_begin_with_the_word # Validates an attribute does not end with the provided string, or strings. # Examples: # validates_does_not_end_with_the_word :username, '2000' # or # validates_does_not_end_with_the_words :username, %w(xxx ooo 666 McFly) # def validates_does_not_end_with_the_word(*attr_names) validates_attributes_not_format_of_block(attr_names) { |word| "#{word}$" } end alias :validates_does_not_end_with_the_words :validates_does_not_end_with_the_word # Validates an attribute does not contain disallowed words # Examples: # validates_does_not_have_the_word :username, 'admin' # or # validates_does_not_have_the_words :username, %w(admin guest moderator) # def validates_does_not_have_the_word(*attr_names) validates_attributes_not_format_of_block(attr_names) { |word| word } end alias :validates_does_not_have_the_words :validates_does_not_have_the_word def validates_is_not_the_word(*attr_names) validates_attributes_not_format_of_block(attr_names) { |word| "^#{word}$" } end alias :validates_is_not_the_words :validates_is_not_the_word private # The block supplied to validates_attributes_not_format_of_block must yield a string # that can be converted into a regular expression by Regexp.new # # The argument supplied to the block is a string that has been regular-expression-quoted, # and is safe to use without further escaping. # # You can pass options for how the regular expression is created in the final options hash. # Either use :ignore_case => true # or # :regexp_options => Fixnum # either of which will be passed as the 2nd argument to Regexp.new, with :regexp_options taking precedence # See documentation on Regexp.new for more information on allowable values for :regexp_options # def validates_attributes_not_format_of_block(attr_names, &block) options = attr_names.last.is_a?(Hash) ? attr_names.pop : { } word = attr_names.pop words = word.respond_to?(:each) ? word : [ word ] regexp_options = options.delete(:regexp_options) || options.delete(:ignore_case) restriction = Regexp.new(words.map { |w| "(#{yield Regexp.quote(w.to_s)})" }.join('|'), regexp_options) configuration = { # Overridable default configuration :message => 'is not valid', :on => :save }.merge(options || {}).merge( # Mandatory default configuration :with => restriction ) validates_not_format_of attr_names, configuration end end end end
Leave a Comment