validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validates_acceptance_of validates_associated validates_confirmation_of validates_each validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of validates_numericality_of validates_presence_of validates_size_of validates_uniqueness_of
validate
methodvalidate
method accepts an attribute and a hash with validation options. This means that now the usual validation can be written like this:
class Person < ActiveRecord::Base validates :email, :presence => true end
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
:acceptance => Boolean :confirmation => Boolean :exclusion => { :in => Ennumerable } :inclusion => { :in => Ennumerable } :format => { :with => Regexp } :length => { :minimum => Fixnum, maximum => Fixnum, } :numericality => Boolean :presence => Boolean :uniqueness => Boolean
class User < ActiveRecord::Base validates :name, :presence => true, :length => {:minimum => 1, :maximum => 254} validates :email, :presence => true, :length => {:minimum => 3, :maximum => 254}, :uniqueness => true, :format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[az]{2,})$/i} end
Thus, now you can immediately look at the model to see which validations are attached for each attribute - that there is a small victory for the code and readability :)
:format => {:with => EmailRegexp}
, a bit heavy to write it in several places, which suggests the idea of ​​creating reusable validation, which could be applied to other models.
email_validator.rb
file in the lib
directory, in the depths of our application:
# lib/email_validator.rb class EmailValidator < ActiveModel::EachValidator EmailAddress = begin qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]' dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]' atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' + '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+' quoted_pair = '\\x5c[\\x00-\\x7f]' domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d" quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22" domain_ref = atom sub_domain = "(?:#{domain_ref}|#{domain_literal})" word = "(?:#{atom}|#{quoted_string})" domain = "#{sub_domain}(?:\\x2e#{sub_domain})*" local_part = "#{word}(?:\\x2e#{word})*" addr_spec = "#{local_part}\\x40#{domain}" pattern = /\A#{addr_spec}\z/ end def validate_each(record, attribute, value) unless value =~ EmailAddress record.errors[attribute] << (options[:message] || " ") end end end
lib
directory is loaded automatically, and since our validator inherits from the ActiveModel::EachValidator
, our class name is used as a dynamic validator that can be used in any object that has access to ActiveModel::Validations
. Ie, for example, these are all objects of ActiveRecord.
User
class will now look like this:
# app/models/person.rb class User < ActiveRecord::Base validates :name, :presence => true, :length => {:minimum => 1, :maximum => 254} validates :email, :presence => true, :length => {:minimum => 3, :maximum => 254}, :uniqueness => true, :email => true end
:email => true
? So much easier, but most importantly - now it can be used anywhere!
$ ./script/console Loading development environment (Rails 3.0.pre) ?> u = User.new(:name => 'Mikel', :email => 'bob') => #<User id: nil, name: "Mikel", email: "bob", created_at: nil, updated_at: nil> >> u.valid? => false >> u.errors => #<OrderedHash {:email=>[" "]}>
user
, visitor
and customer
), each of which must use general validations. In this case, replacing validates
with validates_with
, we just have to do this:
# app/models/person.rb class User < ActiveRecord::Base validates_with HumanValidator end # app/models/person.rb class Visitor < ActiveRecord::Base validates_with HumanValidator end # app/models/person.rb class Customer < ActiveRecord::Base validates_with HumanValidator end
lib
directory:
class HumanValidator < ActiveModel::Validator def validate(record) record.errors[:base] << "This person is dead" unless check(human) end private def check(record) (record.age < 200) && (record.age > 0) end end
$ ./script/console Loading development environment (Rails 3.0.pre) >> u = User.new => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil> >> u.valid? => false >> u.errors => #<OrderedHash {:base=>["This person is dead"]}>
:on :if :unless :allow_blank :allow_nil
:on :if :unless :allow_blank :allow_nil
:on :if :unless :allow_blank :allow_nil
:on :if :unless :allow_blank :allow_nil
:on :if :unless :allow_blank :allow_nil
class Person < ActiveRecord::Base validates :post_code, :presence => true, :unless => :no_postcodes? def no_postcodes? true if ['TW'].include?(country_iso) end end
This will probably be enough to make a first impression about the new level of flexibility.Source: https://habr.com/ru/post/82841/