7.6. ActiveRecord Validations

Validations are a feature that enables you to specify certain rules before a record is created or updated in the database. Several high-level helpers are provided for the most common tasks, but it's good to know the three generic validation methods that allow you to perform validations based on a method that you've defined. These are validate, validate_on_create, and validate_on_update.

When you define a validation rule with validate, ActiveRecord applies that rule to determine whether or not the object should be saved. If the object fails the validation, it's not saved and an error message is added to it so that, in the context of Rails, the view can display it to the user again, who can correct the error by changing the data in the form and trying to resubmit it.

validate_on_create is similar to validate, but it's triggered only when a new record is being created, not when this is being updated. Vice versa, validate_on_update validates attempts to update a record, but not the creation of new ones. The method valid? can also be used to trigger all the existing validations defined for a model object.

Because the method save is used for both the creation and the update of a record, how does ActiveRecord know which of the two operations it needs to perform? The answer is that it uses the new_record? method, which returns true if it's a new record (wherein an INSERT is performed), or false, in which case an UPDATE statement is issued,

You'll also notice that when you create a new record, it doesn't have an id, because the primary key is auto-generated. If it's an existing record, its id will not be nil.

When using any of these three generic validation methods, error messages for a specific attribute are added with the method errors.add(:column_name, message), whereas errors for the whole object are added through errors.add_to_base(message). The error for a specific attribute can be retrieved through the method errors.on(:attribute_name) (and its alias errors[:attribute_name]). Clearing the error messages for an object can be accomplished by using the method errors.clear.

Let's see a practical example of how you can use these methods to define validation rules:

class Book < ActiveRecord::Base
  validate :valid_page_count?
  validate_on_creation :unique_book?

  private

  def valid_page_count?
    unless pages && pages > 48
      errors.add(:pages, "is missing or less than 49")
    end
  end

  def unique_book?
    if Book.find_by_isbn(isbn)
      errors.add(:isbn, "exists already")
    end
  end
end

By passing the symbol :valid_page_count? to validate, you instructed ActiveRecord to execute the private method valid_page_count? before allowing any insert or update. The method adds an error message for the attribute pages, if it has been assigned a value that's less than 49 (or if no value was assigned).

Likewise, by passing :unique_book? to validate_on_creation, the private method unique_book? is invoked upon an attempt to create a record for a new book. This method tries to find the book through its ISBN among the existing ones and, if it can, it adds an error for the attribute that indicates that the book already exists in the database.

These two methods are private because you most likely don't want Book objects to be able to invoke them directly. These methods can also be used in their block form.

If Book didn't have an isbn attribute, the finder probably should have searched for a book with the same title, author, and publisher. In such instances, where multiple attributes are involved, errors.add_to_base("The book exists already") would be used to add an error for the whole object.

7.6.1. Validation Helpers

While building the basic blog application you didn't use validate (or its variants), but rather high-level helpers such as validate_presence_of and validates_uniqueness_of. The creators of ActiveRecord tried to simplify our lives by providing a series of helpers for common validation purposes as follows:

  • validates_acceptance_of: Handy when trying to validate the acceptance of an agreement.

  • validates_associated: Validates any kind of associated object.

  • validates_confirmation_of: Used to validate a confirmation for a field like email address or password.

  • validates_each: Used to validate multiple attributes against a block.

  • validates_exclusion_of: Validates that the value of the specified attribute is not within an enumerable object provided.

  • validates_format_of: Validates the value of the specified attribute against a provided regular expression.

  • validates_inclusion_of: Validates that the value of the specified attribute is an element of an enumerable object provided. It's the opposite of validates_exclusion_of.

  • validates_length_of: Validates the length of a specified attribute value against provided restrictions. It has an alias called validates_size_of.

  • validates_numericality_of: Validates whether a specified attribute value is numeric.

  • validates_presence_of: Validates that the specified attribute value exists by employing the method blank?. Because of this, the object won't pass the validation if the attribute value is nil or, for example, an empty string.

  • validates_uniqueness_of: Validates whether the value of the specified attribute is unique or whether it already exists in the table. For example, to verify that a book is unique (as you did before), you can just use validates_uniqueness_of :isbn. An index is often added to the column represented by the specified attribute, as means of further guaranteeing uniqueness, even when dealing with concurrent transactions.

NOTE

Do not use validates_presence_of to validate Booleans because false.blank? evaluates to true. Use validates_inclusion_of :attribute_name, :in => [false, true] instead.

All of them have a default message (that used to be defined in ActiveRecord::Errors.default_error_messages), which can be overwritten with the :message option. Conversely, you can have conditional validations by using the options :if or :unless, which accept a symbol (for a method that defines the condition), a string (evaluated by eval), or a Proc object.

NOTE

ActiveRecord::Errors.default_error_messages has been deprecated in Rails 2.2.2, and replaced by I18n.translate 'activerecord.errors.messages'.

All three of them should return true or false, and both the method and the Proc object receive the current model instance as an argument:

class Book < ActiveRecord::Base
  validates_presence_of :title, :author, :publisher
  validates_uniqueness_of :isbn, :message => "must be unique"
  validates_length_of :pages, :in => 49..3000, :allow_nil => false
  validates_presence_of :sales, :if => Proc.new { |book| book.published == true })
end

validate had the validate_on_creation and validate_on_update variants. These additional versions are not necessary for the preceding helper methods, because the :on option is used instead. This accepts the values :save, :create, and :update:

validates_format_of :email, :with => /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})
/i, :on => :create

Please consult the online documentation for these methods — defined in the module ActiveRecord::Validations::ClassMethods — to see examples and the exact options available for each.

When none of the validation helpers is sufficient for the rule that you want to enforce, you'll always able to fall back on validate, validate_on_creation, and validate_on_update.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.176.80