Details of the belongs_to relationship in Ruby

A belongs_to relationship creates a one-to-one correspondence with another model. In database terms, this relationship says that this class contains a foreign key. If the foreign key contains another class, has_one should be used instead.

Methods added by belongs_to

When you declare a belongs_to relationship, the declaring class automatically receives five methods related to the relationship:

association

association=(associate)

build_association(attributes = {})

create_association(attributes = {})

create_association!(attributes = {})

reload_association

In all four methods, association is replaced by the character passed as the first argument to belongs_to. For example, we have a declaration:

classBook < ApplicationRecord

  belongs_to :author

end

Each instance of the Book model will have these methods:

author

author=

build_author

create_author

create_author!

reload_author

NOTE: When establishing a new has_one or belongs_to association, you must use the build_ prefix to build the association, as opposed to the association.build method used for has_many or has_and_belongs_to_many associations. To create an association, use the create_ prefix.

association

The association method returns the associated object, if any. If there is no object, returns nil.

@author = @book.author

If the associated object has already been retrieved from the database for that object, the cached version is returned. To override this behavior (and force it to read from the database), call #reload_association on the parent object.

@author = @book.reload_author

association=(associate)

The association= method binds an associated object to that object. In effect, this means extracting the primary key from the related entity and assigning its value to the foreign key.

@book.author = @author

build_association(attributes = {})

The build_association method returns a new object of the associated type. This object will be an instance with the attributes passed in, a relationship will be established with the foreign key of this object, but the associated object will not be saved yet.

@author = @book.build_author(author_number: 123,

                                  author_name: “John Doe”)

create_association(attributes = {})

The create_association method returns a new object of the associated type. This entity will be an instance with the attributes passed in, a relationship will be established with the entity’s foreign key, and if it passes the validations defined in the associated model, the associated entity will be saved.

@author = @book.create_author(author_number: 123,

                                   author_name: “John Doe”)

create_association!(attributes = {})

Works the same as create_association above, but calls ActiveRecord::RecordInvalid if the record is invalid.

(options-for-belongs-to) Options for belongs_to

While Rails uses reasonable defaults that work in many situations, there are times when you want to change the behavior of a belongs_to relationship. This customization is easily done by passing options and scoped blocks when creating a link. For example, this link uses two of these options:

classBook < ApplicationRecord

  belongs_to :author, dependent: :destroy,

    counter_cache: true

end

The belongs_to relationship supports these options:

:autosave

:class_name

:counter_cache

:dependent

:foreign_key

:primary_key

:inverse_of

:polymorphic

:touch

:validate

:optional

:autosave

If you set the :autosave option to true, Rails will save any loaded related members and destroy members marked for destruction whenever the parent object is saved. But setting :autosave to false is not the same as not setting the :autosave option. If the :autosave option is not present, then new related objects will be saved, but updated related objects will not be saved.

:class_name

If the name of another model cannot be derived from the link name, you can use the :class_name option to provide the name of the model. For example, if the book is owned by the author, but the actual name of the model containing the authors is Patron, you can set this as follows:

classBook < ApplicationRecord

  belongs_to :author, class_name: “Patron”

end

:counter_cache

The :counter_cache option can be used to make finding the number of owned objects more efficient. Consider these models:

classBook < ApplicationRecord

  belongs_to :author

end

classAuthor<ApplicationRecord

  has_many:books

end

With these declarations, requesting the @author.books.size value requires a database call to execute the COUNT(*) request. To avoid this, you can add a counter cache to the owned model:

classBook < ApplicationRecord

  belongs_to :author, counter_cache: true

end

classAuthor<ApplicationRecord

  has_many:books

end

With this declaration, Rails will cache the actual value and then return that value in response to the size method.

:polymorphic

Passing true for the :polymorphic option indicates that this is a polymorphic relationship. Polymorphic relationships have been discussed in detail previously.

:touch

If you set the :touch option to true, then the updated_at or updated_on timestamps on the associated object will be set to the current time whenever that object is saved or destroyed:

classBook < ApplicationRecord

  belongs_to :author, touch: true

end

classAuthor<ApplicationRecord

  has_many:books

end

In this case, saving or destroying the book will update the timestamp on the associated author. You can also define a specific timestamp attribute to update:

classBook < ApplicationRecord

  belongs_to :author, touch: :books_updated_at

end

:validate

If you set the :validate option to true, then related objects will be validated whenever you save that object. It defaults to false: related objects are not validated when this object is saved.

:optional

If you set :optional to true, then the presence of related objects will not be validated. The default is set to false.

Scopes for belongs_to

Sometimes you want to customize the query used by belongs_to. Such customization can be achieved with a scope block. For example:

classBook < ApplicationRecord

  belongs_to :author, -> { where active: true },

                        dependent: :destroy

end

Within a scope block, any standard query methods can be used. Next, we will discuss the following ones:

where

includes

readonly

select

where

The where method allows you to specify the conditions that the associated object must meet.

classBook < ApplicationRecord

  belongs_to :author, -> { where active: true }

end

includes

The includes method can be used to define second-order relationships that should be lazily loaded when using this relationship. For example, consider these models:

class LineItem < ApplicationRecord

  belongs_to :book

end

classBook < ApplicationRecord

  belongs_to :author

  has_many :line_items

end

classAuthor<ApplicationRecord

  has_many:books

end

If you often get authors directly from the elements (@line_item.book.author), then you can improve code efficiency by including the authors in the relationship between the book and its elements: NOTE: There is no need to use includes for nearest links – that is, if there is a Book belongs_to :author , the author is automatically lazy loaded when needed.

Rails Active Record Connection

has_many connection

A has_many relationship indicates a one-to-many connection to another model. This relationship is often on the “other side” of the belongs_to relationship. This relationship indicates that each model instance has zero or more instances of another model. For example, in an application containing authors and books, the author model might be declared like this:

classAuthor<ApplicationRecord

  has_many:books

end

NOTE: The name of the other model is plural when declaring the has_many relationship.

Diagram for has_many connection

The corresponding migration might look like this:

class CreateAuthors < ActiveRecord::Migration[5.0]

  def change

    create_table :authors do |t|

      t.string :name

      t.timestamps

    end

(the-has-many-through-association) has_many :through association

A has_many :through relationship is often used to set up a many-to-many connection with another model. This relationship indicates that the declaring model can match zero or more instances of another model via a third model. For example, consider a polyclinic where patients are given appointments to see physicians (physicians). The corresponding link declarations would look like this:

class Physician < ApplicationRecord

  has_many:appointments

  has_many :patients, through: :appointments

end

class Appointment < ApplicationRecord

  belongs_to :physician

  belongs_to :patient

end

class Patient < ApplicationRecord

  has_many:appointments

  has_many :physicians, through: :appointments

end

The collection of connection models can be managed using the has_many connection methods. For example, if you assign:

physician.patients = patients

Then new connection models for newly connected objects will be automatically created. If some of the previously existing ones are now missing, their connector strings are automatically removed.

WARNING: Automatic deletion of join models is straightforward, none of the kill callbacks are included.

The has_many :through relationship is also useful for setting “shortcuts” through nested has_many relationships. For example, if a document has many sections, and a section has many paragraphs, sometimes you want to get just a collection of all the paragraphs in the document. This can be configured like this:

With through: :sections defined, Rails now understands:

@document.paragraphs

(the-has-one-through-association) has_one :through association

The has_one :through relationship sets up a one-to-one connection with another model. This relationship indicates that the declaring model can be related to one instance of another model through a third model. For example, if each supplier has one account, and each account is associated with one account history, then the models might look like this:

The corresponding migration might look like this:

has_and_belongs_to_many relationship

A has_and_belongs_to_many relationship creates a direct many-to-many connection to another model, with no intermediate model. For example, if your application includes assemblies and parts (parts), where each node has many parts, and each part occurs in many assemblies, the models can be declared like this:

class Assembly < ApplicationRecord

  has_and_belongs_to_many :parts

end

class Part<ApplicationRecord

  has_and_belongs_to_many :assemblies

end

Diagram for has_and_belongs_to_many relationship

The corresponding migration might look like this:

class CreateAssembliesAndParts < ActiveRecord::Migration[5.0]

  def change

    create_table :assemblies do |t|

      t.string :name

      t.timestamps

    end

    create_table :parts do |t|

      t.string :part_number

      t.timestamps

    end

    create_table :assemblies_parts, id: false do |t|

      t.belongs_to :assembly, index: true

      t.belongs_to :part, index: true

    end

  end

end

Choice between belongs_to and has_one

If you want to set up a one-to-one relationship between two models, you need to add belongs_to to one and has_one to the other. How to find out which is which?

The difference is where the foreign key is placed (it must be in the table for the class declaring the belongs_to relationship), but you also have to think about the actual meaning of the data. The has_one relation says that something belongs to you – that is, that something points to you. For example, it makes more sense that the supplier owns the account than that the account owns the supplier. This means that the correct relationship is like this:

class Supplier < ApplicationRecord

  has_one :account

end

class Account < ApplicationRecord

  belongs_to :supplier

end

The corresponding migration might look like this:

class CreateSuppliers < ActiveRecord::Migration[5.0]

  def change

    create_table :suppliers do |t|

      t.string :name

      t.timestamps

    end

    create_table :accounts do |t|

      t.integer :supplier_id

      t.string :account_number

      t.timestamps

    end

    add_index :accounts, :supplier_id

  end

end

NOTE: The use of t.integer :supplier_id specifies the foreign key name explicitly and explicitly. In modern versions of Rails, you can abstract away implementation details using t.references :supplier.

Choosing between has_many :through and has_and_belongs_to_many

Rails provides two different ways to declare a many-to-many relationship between models. The simplest way is to use has_and_belongs_to_many which allows you to create a relationship directly:

class Assembly < ApplicationRecord

  has_and_belongs_to_many :parts

end

class Part<ApplicationRecord

  has_and_belongs_to_many :assemblies

end

The second way to declare a many-to-many relationship is to use has_many :through. This does not communicate directly, but through a connecting model:

class Assembly < ApplicationRecord

  has_many :manifests

  has_many :parts, through: :manifests

end

class Manifest < ApplicationRecord

  belongs_to :assembly

  belongs_to :part

end

class Part<ApplicationRecord

  has_many :manifests

  has_many :assemblies, through: :manifests

end

The simplest sign that you need to set up a has_many :through relationship is if you want to treat the relationship model as an independent entity. If you don’t need to do anything with the relationship model, it’s easier to set up a has_and_belongs_to_many relationship (though remember to create a join table in the database).

You should use has_many :through if you need validations, callbacks, or additional attributes for the join model.

(polymorphic-associations)

Polymorphic relationships are a slightly more “fancy” kind of relationship. With polymorphic relationships, a model can belong to more than one model, on a single relationship. For example, there is an image model that belongs to either a worker model or a product model. Here’s how it’s declared:

class Picture < ApplicationRecord

  belongs_to :imageable, polymorphic: true

end

class Employee < ApplicationRecord

  has_many :pictures, as: :imageable

end

class Product < ApplicationRecord

  has_many :pictures, as: :imageable

end

You can think of a polymorphic belongs_to declaration as setting up an interface that any other model can use. From an instance of the Employee model, you can get a collection of images: @employee.pictures.

Similarly, you can get @product.pictures.

If you have an instance of the Picture model, you can get its parent using @picture.imageable. For this to work, you must declare a foreign key column and a type column in the model that declares the polymorphic interface:

class CreatePictures < ActiveRecord::Migration[5.0]

  def change

    create_table :pictures do |t|

      t.string :name

      t.integer :imageable_id

      t.string :imageable_type

      t.timestamps

    end

    add_index :pictures, [:imageable_type, :imageable_id]

  end

end

This migration can be simplified using the t.references form:

Transactional callbacks in Ruby on Rails

There are two additional callbacks that are fired when a database transaction completes: after_commit and after_rollback. These callbacks are very similar to the after_save callback, except that they are not fired until the database changes have been committed or reversed. They are most useful when your Active Record models need to interact with external systems that are not part of the database transaction.

Consider, for example, the previous example where the PictureFile needs to delete the file after the record is destroyed. If anything throws an exception after the after_destroy callback has been called and the transaction is rolled back, the file will be deleted and the model will be left in an inconsistent state. For example, suppose picture_file_2 in the following code is not valid and the save! will cause an error.

PictureFile.transaction do

  picture_file_1.destroy

  picture_file_2.save!

end

Using the after_commit callback, this case can be taken into account.

class PictureFile < ApplicationRecord

  after_commit :delete_picture_file_from_disk, on: :destroy

  def delete_picture_file_from_disk

    if File.exist?(filepath)

      File.delete(filepath)

    end

  end

end

NOTE: The :on option determines when the callback will run. If you don’t provide the :on option, the callback will be fired for each action.

Since it is customary to use the after_commit callback only when creating, updating, or deleting, there are aliases for these operations:

after_create_commit

after_update_commit

after_destroy_commit

class PictureFile < ApplicationRecord

  after_destroy_commit :delete_picture_file_from_disk

  def delete_picture_file_from_disk

    if File.exist?(filepath)

      File.delete(filepath)

    end

  end

end

WARNING: The after_commit and after_rollback callbacks are called on all created, updated, or deleted models within a transaction block. However, if any exception is thrown in one of these callbacks, that exception will be bubbled up and any remaining after_commit or after_rollback methods will not be executed. Basically, if your callback code could throw an exception, you should call rescue on it, and handle it in the callback to allow other callbacks to run.

WARNING. When using after_create_commit and after_update_commit at the same time on the same model, only the last defined callback will fire, overriding all others.

class User<ApplicationRecord

  after_create_commit :log_user_saved_to_db

  after_update_commit :log_user_saved_to_db

  private

  def log_user_saved_to_db

    puts ‘User was saved to database’

  end

end

# output nothing

>> @user = User.create

# update @user

>> @user.save

=> User was saved to database

To register callbacks for both create and update actions, use after_commit.

class User<ApplicationRecord

  after_commit :log_user_saved_to_db, on: [:create, :update]

end

Active Record Links

This guide covers the specifics of Active Record links.

After reading it, you will know:

How to declare relationships between Active Record models.

How to understand the different types of Active Record relationships.

How to use methods added to your models when creating relationships.

Why are connections needed?

In Rails, a relationship is a connection between two Active Record models. Why do we need links between models? Because they allow you to make the code for common operations simpler and easier. For example, consider a simple Rails application that includes an author model and a book model. Each author can have many books. Without relationships, the model declaration would look like this:

classAuthor<ApplicationRecord

end

classBook < ApplicationRecord

end

Now let’s say we want to add a new book for an existing author. We need to do this:

@book = Book.create(published_at: Time.now, author_id: @author.id)

Or, let’s say we delete the author and make sure that all his books will also be deleted:

@books = Book.where(author_id: @author.id)

@books.each do |book|

  book.destroy

end

@author.destroy

With Active Record relationships, you can simplify these and other operations by declaratively telling Rails that there is a connection between two models. Here is the revised code for creating authors and books:

classAuthor<ApplicationRecord

  has_many :books, dependent: :destroy

end

classBook < ApplicationRecord

  belongs_to :author

end

With these changes, creating a new book for a specific author is easier:

@book = @author.books.create(published_at: Time.now)

Removing an author and all his books is much easier:

@author.destroy

To learn more about the different types of links, read the next section of the guide. This is followed by some helpful hints for working with relationships, followed by a full description of the methods and options for relationships in Rails.

Relationship types

Rails supports six types of links:

belongs_to

has_one

has_many

has_many :through

has_one :through

has_and_belongs_to_many

Relationships are implemented using macro-style calls, so you can add features to your models declaratively. For example, by declaring that one model belongs (belongs_to) another, you tell Rails to keep the primary-foreign key information between instances of the two models, and you get a few useful methods added to the model.

After reading this entire tutorial, you will learn how to declare and use various forms of relationships. But first, you should quickly familiarize yourself with the situations when each type of communication is applicable.

belongs_to relationship

A belongs_to relationship establishes a one-to-one connection with another model when one instance of the declaring model “belongs” to one instance of the other model. For example, if your application has authors and books, and one book can only be associated with one author, you would declare the book model as follows:

classBook < ApplicationRecord

  belongs_to :author

end

Diagram for belongs_to relationship

NOTE: belongs_to relationships must be singular. If you use the plural in the example above for the author relationship in the Book model, you will be told “uninitialized constant Book::Authors”. This is because Rails automatically derives the class name from the association name. If a number is incorrectly used in the association name, the resulting class will also be the wrong number.

The corresponding migration might look like this:

class CreateOrders < ActiveRecord::Migration[5.0]

  def change

    create_table :authors do |t|

      t.string :name

      t.timestamps

    end

    create_table :books do |t|

      t.belongs_to :author, index: true

      t.datetime :published_at

      t.timestamps

    end

  end

end

has_one connection

The has_one relationship also establishes a one-to-one connection with another model, but in a slightly different sense (and with different implications). This relationship indicates that each model instance contains or owns one instance of the other model. For example, if each supplier has only one account, you can declare a supplier model like this:

class Supplier < ApplicationRecord

  has_one :account

end

Diagram for has_one connection

The corresponding migration might look like this:

class CreateSuppliers < ActiveRecord::Migration[5.0]

  def change

    create_table :suppliers do |t|

      t.string :name

      t.timestamps

    end

    create_table :accounts do |t|

      t.belongs_to :supplier, index: true

      t.string :account_number

      t.timestamps

    end

  end

end

Depending on the application, it may be necessary to create a unique index and/or foreign key constraint on the specified column in the accounts table. In this case, the column definition might look like this:

create_table :accounts do |t|

  t.belongs_to :supplier, index: { unique: true }, foreign_key: true

  # …

end

Callbacks in Rails

WARNING. after_save is fired on both creation and update, but always after the more specific after_create and after_update callbacks, regardless of the order in which the macro calls are fired.

NOTE: The before_destroy callback must be placed before dependent: :destroy bindings (or use the prepend: true option) to ensure that they are executed before the entries are removed with dependent: :destroy.

after_initialize and after_find

The after_initialize callback is called whenever an Active Record object is instantiated, either directly by using new, or when a record is loaded from the database. It can be useful to avoid having to directly override the Active Record initialize method.

The after_find callback will be called whenever Active Record loads a record from the database. after_find is called before after_initialize if both are defined.

The after_initialize and after_find callbacks do not have a before_* pair, but they can be registered like other Active Record callbacks.

class User<ApplicationRecord

  after_initialize do |user|

    puts “You have initialized an object!”

  end

  after_find do |user|

    puts “You have found an object!”

  end

end

>> User.new

You have initialized an object!

=> #<User id: nil>

>> User.first

You have found an object!

You have initialized an object!

=> #<User id: 1>

after_touch

The after_touch callback will be called when touch is called on an Active Record object.

class User<ApplicationRecord

  after_touch do |user|

    puts “You have touched an object”

  end

end

>> u = User.create(name: ‘Kuldeep’)

=> #<User id: 1, name: “Kuldeep”, created_at: “2013-11-25 12:17:49”, updated_at: “2013-11-25 12:17:49”>

>>u.touch

You have touched an object

=> true

It can be used in conjunction with belongs_to:

class Employee < ApplicationRecord

  belongs_to :company, touch: true

  after_touch do

    puts ‘An Employee was touched’

  end

end

classCompany < ApplicationRecord

  has_many:employees

  after_touch :log_when_employees_or_company_touched

  private

  def log_when_employees_or_company_touched

    puts ‘Employee/Company was touched’

  end

end

>> @employee = Employee.last

=> #<Employee id: 1, company_id: 1, created_at: “2013-11-25 17:04:22”, updated_at: “2013-11-25 17:05:05”>

# calls @employee.company.touch

>> @employee.touch

Employee/Company was touched

An employee was touched

=> true

Running callbacks

The following methods fire callbacks:

create

create!

destroy

destroy!

destroy_all

save

save!

save(validate: false)

toggle!

update_attribute

update

update!

valid?

Additionally, the after_find callback is fired by the following find methods:

all

first

find

find_by

find_by_*

find_by_*!

find_by_sql

last

The after_initialize callback is fired whenever a new class object is initialized.

NOTE: The find_by_* and find_by_* methods! these are dynamic lookup methods generated automatically for each attribute. Learn more about them in the Dynamic Search section.

Skipping callbacks

Similar to validations, it is also possible to skip callbacks using the following methods.

decrement

decrement_counter

delete

delete_all

increment

increment_counter

toggle

touch

update_column

update_columns

update_all

update_counters

However, these methods must be used with care as important business rules and application logic can be contained in callbacks. Skipping them without understanding the possible consequences can lead to invalid data.

Interrupt execution

As soon as you have registered new callbacks in your models, they will be queued for execution. This queue includes all your model validations, registered callbacks, and database operations to perform.

The entire chain of callbacks is packaged into an operation. If any callback throws an exception, the running chain is aborted and ROLLBACK is started. To intentionally stop a chain, use:

throw :abort

WARNING. Throwing an arbitrary exception can break code that assumes that save and the like will not fail like this. The ActiveRecord::Rollback exception tells Active Record a bit more precisely that a rollback is in progress. It is picked up from within, but does not rethrow the exception.

WARNING. Any exception other than ActiveRecord::Rollback or ActiveRecord::RecordInvalid will be rethrown by Rails after the callback chain breaks. Throwing an exception other than ActiveRecord::Rollback or ActiveRecord::RecordInvalid can break code that doesn’t expect methods like save and update_attributes (which usually try to return true or false) to throw an exception.

Relationship Callbacks

Callbacks work with relationships between models, and can even be defined by them. Imagine an example where a user has many articles. The user’s articles must be destroyed if the user is destroyed. Let’s add an after_destroy callback to the User model through its relationship with the Article model.

Conditional callbacks

As with validations, it is possible to make a callback method call conditional depending on a given predicate. This is done using the :if and :unless options, which can take a character, a Proc, or an array. The :if option should be used to determine under what conditions the callback should be called. If you want to specify conditions under which the callback should not be called, use the :unless option.

Using :if and :unless with a symbol

The :if and :unless options can be bound to a symbol corresponding to the name of the predicate method that will be called just before the callback is called. When using the :if option, the callback will not be executed if the predicate method returns false; when using the :unless option, the callback will not be executed if the predicate method returns true. This is the most common option. When using this form of registration, it is also possible to register several different predicates that will be called to check if the callback should run.

classOrder < ApplicationRecord

  before_save :normalize_card_number, if: :paid_with_card?

end

Using :if and :unless with Proc

Finally, you can bind :if and :unless to the Proc object. This option is most suitable when writing short methods, usually one-liners.

classOrder < ApplicationRecord

  before_save :normalize_card_number,

    if: Proc.new { |order| order.paid_with_card? }

end

Compound conditions for callbacks

When writing conditional callbacks, it is possible to mix :if and :unless in the same callback declaration.

class Comment < ApplicationRecord

  after_create :send_email_to_author, if: :author_wants_emails?,

    unless: Proc.new { |comment| comment.article.ignore_comments? }

end

Callback classes

Sometimes the callback methods you write are useful enough to be reused in other models. Active Record makes it possible to create classes that include callback methods so that it becomes very easy to reuse them.

Here is an example where a class is created with an after_destroy callback for the PictureFile model:

class PictureFileCallbacks

  def after_destroy(picture_file)

    if File.exist?(picture_file.filepath)

      File.delete(picture_file.filepath)

    end

  end

end

When declared within a class, as above, the callback methods receive the model object as a parameter. Now we can use the callback class in the model:

class PictureFile < ApplicationRecord

  after_destroy PictureFileCallbacks.new

end

Note that we need to instantiate a new PictureFileCallbacks object after we have declared our callback as a separate method. This is especially useful if callbacks use the state of an object instance. Often, however, it is more appropriate to declare it as a class method.

class PictureFileCallbacks

  def self.after_destroy(picture_file)

    if File.exist?(picture_file.filepath)

      File.delete(picture_file.filepath)

    end

  end

end

If the callback method is declared this way, there is no need to instantiate the PictureFileCallbacks object.

class PictureFile < ApplicationRecord

  after_destroy PictureFileCallbacks

end

Inside your callback class, you can create as many callbacks as you like.

Rails built-in validators

All Rails built-in validators populate the details hash with the appropriate validator type.

errors[:base]

You can add error messages that refer to the state of the object as a whole rather than to a single attribute. This method can be used if you want to say that an object is invalid, regardless of the values ​​of its attributes. Since errors[:base] is an array, you can simply add a string to it and it will be used as the error message.

classPerson < ApplicationRecord

  def a_method_used_for_validation_purposes

    errors[:base] << “This person is invalid because …”

  end

end

errors.clear

The clear method is used when you intentionally want to clear all messages in the errors collection. Naturally, calling errors.clear on an invalid object won’t actually make it valid: right now, the errors collection will be empty, but the next time you call valid? or any method that tries to save that object to the database, the validations will run again. If any of the validations fail, the errors collection will be populated again.

classPerson < ApplicationRecord

  validates :name, presence: true, length: { minimum: 3 }

end

person = Person.new

person.valid? # => false

person.errors[:name]

 # => [“can’t be blank”, “is too short (minimum is 3 characters)”]

person.errors.clear

person.errors.empty? # => true

person.save # => false

person.errors[:name]

 # => [“can’t be blank”, “is too short (minimum is 3 characters)”]

errors.size

The size method returns the number of error messages for the object.

classPerson < ApplicationRecord

  validates :name, presence: true, length: { minimum: 3 }

end

person = Person.new

person.valid? # => false

person.errors.size # => 2

person = Person.new(name: “Andrea”, email: “[email protected]”)

person.valid? # => true

person.errors.size # => 0

(displaying-validation-errors-in-the-view) Display validation errors in views

Once you’ve created a model and added validations, if that model is being created with a web form, then you might want to display an error message when one of the validations fails.

Because each application handles this kind of thing differently, Rails doesn’t have a view helper to generate these messages directly. However, thanks to the rich set of methods, Rails in general gives a way to interact with validations, it’s very easy to create your own. Also, when generating a scaffold, Rails will place some ERB in the _form.html.erb generated to display the complete list of errors for that model.

Let’s say we have a model stored in the @article instance variable, it looks like this:

<% if @article.errors.any? %>

  <div id=”error_explanation”>

    <h2><%= pluralize(@article.errors.count, “error”) %> prohibited this article from being saved:</h2>

    <ul>

    <% @article.errors.full_messages.each do |msg| %>

      <li><%= msg %></li>

    <% end %>

    </ul>

  </div>

<% end %>

Moreover, when using Rails form helpers to create forms, when a field has a validation error, an extra <div> is generated around the content.

<div class=”field_with_errors”>

 <input id=”article_title” name=”article[title]” size=”30″ type=”text” value=””>

</div>

This div can be styled however you like. For example, the default scaffold that Rails generates adds this CSS rule:

.field_with_errors {

  padding: 2px

  background color: red

  display:table;

}

This means that any field with an error has a 2 pixel red border around it.

Active Record Callbacks

This guide will teach you how to intervene in the lifecycle of your Active Record objects.

After reading this guide, you will know:

About the lifecycle of Active Record objects

How to create callback methods that respond to events in the life cycle of an object

How to create special classes that encapsulate common behavior for your callbacks

Object lifecycle

As a result of the normal operations of a Rails application, objects can be created, updated, and destroyed. Active Record gives you the ability to intervene in this object lifecycle so you can control your application and its data.

Validations allow you to be sure that only valid data is stored in your database. Callbacks allow you to switch logic before or after an object’s state changes.

Callback Overview

Callbacks are methods that are called at specific points in an object’s life cycle. With callbacks, it is possible to write code that will be run when an Active Record object is created, saved, updated, deleted, validated, or loaded from a database.

Registering callbacks

In order to use the available callbacks, they must be registered. You can implement callbacks as normal methods and then use class macro methods to register them as callbacks.

class User<ApplicationRecord

  validates :login, :email, presence: true

  before_validation :ensure_login_has_a_value

  private

    def ensure_login_has_a_value

      if login.nil?

        self.login = email unless email.blank?

      end

    end

end

Class macro methods can also receive a block. They can be used if the code inside the block is so short that it fits on one line.

class User<ApplicationRecord

  validates :login, :email, presence: true

  before_create do

    self.name = login.capitalize if name.blank?

  end

end

Callbacks can also be registered to execute on certain lifecycle events:

class User<ApplicationRecord

  before_validation :normalize_name, on: :create

  # :on also takes an array

  after_validation :set_location, on: [ :create, :update ]

  private

    def normalize_name

      self.name = name.downcase.titleize

    end

    def set_location

      self.location = LocationService.query(self)

    end

end

It is considered good practice to declare callback methods private. If left public, they can be called from outside the model and violate the principles of object encapsulation.

Available callbacks

Here is a list of all available Active Record callbacks, listed in the order they are called during their respective operations:

Create an object

before_validation

after_validation

before_save

around_save

before_create

around_create

after_create

after_save

after_commit/after_rollback

Object update

before_validation

after_validation

before_save

around_save

before_update

around_update

after_update

after_save

after_commit/after_rollback

Object destruction

before_destroy

around_destroy

after_destroy

after_commit/after_rollback

General validation options in Ruby

There are several common validation options:

:allow_nil

The :allow_nil option skips validation when the value being checked is nil.

class Coffee < ApplicationRecord

  validates :size, inclusion: { in: %w(small medium large),

    message: “%{value} is not a valid size” }, allow_nil: true

end

See the message documentation for all message argument options.

:allow_blank

The :allow_blank option is similar to the :allow_nil option. This option skips validation if the value of the attribute is blank?, such as nil or the empty string.

class Topic < ApplicationRecord

  validates :title, length: { is: 5 }, allow_blank: true

end

Topic.create(title: “”).valid? # => true

Topic.create(title: nil).valid? # => true

:message

As we’ve seen, the :message option allows you to specify a message to be added to the errors collection when the validation fails. If this option is not used, Active Record will use the appropriate default error messages for each validation helper. The :message option accepts a String or a Proc.

The String value in :message can optionally contain any of %{value}, %{attribute} and %{model} which will be dynamically replaced when the validation fails. This substitution is performed if the I18n gem is used and the insertion point must match exactly, no spaces are allowed.

The value of Proc in :message is given with two arguments: the object to be checked and a hash with keys :model, :attribute and :value.

classPerson < ApplicationRecord

  # Hardcoded message

  validates :name, presence: { message: “must be given please” }

  # Message with value with dynamic attribute. %{value} will be replaced

  # the actual value of the attribute. %{attribute} and %{model} are also available.

  validates :age, numericality: { message: “%{value} seems wrong” }

  #Proc

  validates :username,

    uniqueness: {

      # object = person object being validated

      # data = { model: “Person”, attribute: “Username”, value: <username> }

      message: ->(object, data) do

        “Hey #{object.name}!, #{data[:value]} is taken already! Try again #{Time.zone.tomorrow}”

      end

    }

end

:on

The :on option allows you to specify when validation should occur. The standard behavior for all built-in validation helpers is to run on save (both when a new record is created and when it is updated). If you want to change this, use on: :create to run validation only when a new post is created, or on: :update to run validation when a post is updated.

classPerson < ApplicationRecord

  # it will be possible to update an email with a duplicate value

  validates :email, uniqueness: true, on: :create

  # it will be possible to create an entry with a non-numeric age

  validates :age, numericality: true, on: :update

  # by default (checks both on creation and update)

  validates :name, presence: true

end

on: can also be used to define a user context. User contexts must be explicitly enabled by passing the context name to valid?, invalid? or save.

classPerson < ApplicationRecord

  validates :email, uniqueness: true, on: :account_setup

  validates :age, numericality: true, on: :account_setup

end

person = Person.new

person.valid?(:account_setup) will do both validations without saving the model. And person.save(context: :account_setup) validates person in the context of account_setup before saving. When explicitly included, the model is validated only by validations of this context only and by validations without context.

Strict validations

It is also possible to define validations as strict so that they call ActiveModel::StrictValidationFailed when the object is not valid.

classPerson < ApplicationRecord

  validates :name, presence: { strict: true }

end

Person.new.valid? # => ActiveModel::StrictValidationFailed: Name can’t be blank

It is also possible to pass your own exception to the :strict option.

classPerson < ApplicationRecord

  validates :token, presence: true, uniqueness: true, strict: TokenGenerationException

end

Person.new.valid? # => TokenGenerationException: Token can’t be blank

Conditional Validation

Sometimes it makes sense to validate an object only if a given predicate is met. This can be done using the :if and :unless options, which take a character, Proc, or Array. The :if option can be used if you want to specify when validation should occur. If you need to specify when validation should not occur, use the :unless option.

Using a symbol with :if and :unless

You can bind the :if and :unless options to a symbol corresponding to the name of the method that will be called before validation. This is the most commonly used option.

classOrder < ApplicationRecord

  validates :card_number, presence: true, if: :paid_with_card?

  def paid_with_card?

    payment_type == “card”

  end

end

Using Proc with :if and :unless

Finally, you can bind :if and :unless to the Proc object that will be called. Using the Proc object makes it possible to write an inline condition instead of a separate method. This option is best for single line code.

class Account < ApplicationRecord

  validates :password, confirmation: true,

    unless: Proc. new { |a| a.password.blank? }

end

Grouping conditional validations

Sometimes it’s useful to have multiple validations with the same condition. This is easily achieved using with_options.

class User<ApplicationRecord

  with_options if: :is_admin? do |admin|

    admin.validates :password, length: { minimum: 10 }

    admin.validates :email, presence: true

  end

end

All validations inside with_options will automatically be passed an if: :is_admin? condition.

Combining Validation Conditions

On the other hand, an array can be used when multiple conditions determine whether validation should occur. Moreover, both :if: and :unless can be used in the same validation.

class Computer < ApplicationRecord

  validates :mouse, presence: true,

                    if: [Proc.new { |c| c.market.retail? }, :desktop?],

                    unless: Proc.new { |c| c.trackpad.present? }

end

Validation will only be performed when all of the :if conditions and none of the :unless conditions evaluate to true.

Performing Your Own Validations

When the built-in validation helpers are not enough for your needs, you can write your own validators or validation methods.

Own validators

Custom validators are classes that inherit from ActiveModel::Validator. These classes must implement a validate method that takes an entry as an argument and performs validation on it. The custom validator is called using the validates_with method.

class MyValidator < ActiveModel::Validator

  def validate(record)

    unless record.name.starts_with? ‘X’

      record.errors[:name] << ‘Need a name starting with X please!’

    end

  end

end

class person

  include ActiveModel::Validations

  validates_with MyValidator

end

The easiest way to add custom validators to validate individual attributes is to inherit from ActiveModel::EachValidator. In this case, the custom validator class must implement the validate_each method, which takes three arguments: entry, attribute, and value. These will be the corresponding instance, the attribute to be checked, and the value of the attribute in the passed instance:

Helpers in Ruby on Rails

numericality

This helper validates that your attributes only have numeric values. By default, this will match the possible sign of the first character, followed by an integer or floating point number. To specify that only integer values ​​are allowed, set :only_integer to true.

If you set :only_integer to true then the regular expression will be used

/\A[+-]?\d+\z/

to validate the attribute value. Otherwise, it will try to convert the value to a number using Float.

classPlayer<ApplicationRecord

  validates :points, numericality: true

  validates :games_played, numericality: { only_integer: true }

end

In addition to :only_integer , the validates_numericality_of helper also accepts the following options to add restrictions to valid values:

:greater_than – Specifies that the value must be greater than the value of the option. The default error message for this option is “must be greater than %{count}”.

:greater_than_or_equal_to – Specifies that the value must be greater than or equal to the value of the option. The default error message for this option is “must be greater than or equal to %{count}”.

:equal_to – Specifies that the value must be equal to the value of the option. The default error message for this option is “must be equal to %{count}”.

:less_than – Specifies that the value must be less than the value of the option. The default error message for this option is “must be less than %{count}”.

:less_than_or_equal_to – Specifies that the value must be less than or equal to the value of the option. The default error message for this option is “must be less than or equal to %{count}”.

:other_than – Specifies that the value must be different from the presented value. The default error message for this option is “must be other than %{count}”.

:odd – Specifies that the value should be odd if set to true. The default error message for this option is “must be odd”.

:even – Specifies that the value must be even if set to true. The default error message for this option is “must be even”.

NOTE: Numerity does not allow nil by default. To allow them, you can use the option allow_nil: true.

The default error message is “is not a number”.

presence

This helper validates that certain attributes are not empty. Does it use the blank method? to check if a value is either nil or an empty string (a string that is either empty or contains spaces).

classPerson < ApplicationRecord

  validates :name, :login, :email, presence: true

end

If you want to be sure that a relationship exists, you need to check if the related object itself exists, not the foreign key used for the relationship.

class LineItem < ApplicationRecord

  belongs_to :order

  validates :order, presence: true

end

In order to check for related records whose presence is needed, you need to define the :inverse_of option for the link:

classOrder < ApplicationRecord

  has_many :line_items, inverse_of: :order

end

When validating the existence of an object associated with a has_one or has_many relationship, it will check that the object is neither blank? nor marked_for_destruction?.

So how is false.blank? is true, if you want to validate the existence of a boolean field, you must use one of the following validations:

validates :boolean_field_name, inclusion: { in: [true, false] }

validates :boolean_field_name, exclusion: { in: [nil] }

When using one of these validations, you can be sure that the value will not be nil, which in most cases will convert to a NULL value.

absence

This helper checks that the specified attributes are missing. Does it use the present? to check that the value is either nil or the empty string (that is, either zero length or consisting of spaces).

classPerson < ApplicationRecord

  validates :name, :login, :email, absence: true

end

If you want to make sure that there is no relationship, you need to check that the related entity itself is missing, not the foreign key used for the relationship.

class LineItem < ApplicationRecord

  belongs_to :order

  validates :order, absence: true

end

To check for related objects that you want to be missing, you need to specify the :inverse_of option for the link:

classOrder < ApplicationRecord

  has_many :line_items, inverse_of: :order

end

If you are checking for the absence of an object associated with a has_one or has_many relationship, it will check that the object is neither present? nor marked_for_destruction?.

Because false.present? is false, if you want to check for the absence of a boolean field, you should use validates :field_name, exclusion: { in: [true, false] }.

The default error message is “must be blank”.

uniqueness

This helper validates that an attribute’s value is unique before the object is saved. It does not create a uniqueness condition in the database, hence it can happen that two different database connections will create two records with the same value for a column you think is unique. To avoid this, you need to create a unique index on both columns in your database.

class Account < ApplicationRecord

  validates :email, uniqueness: true

end

Validation is done by SQL querying the model table, searching for an existing record with the same attribute value.

There is a :scope option that can be used to define one or more attributes used to limit the uniqueness check:

class Holiday < ApplicationRecord

  validates :name, uniqueness: { scope: :year,

    message: “should happen once per year” }

end

If you want to create a database-level constraint to prevent possible uniqueness validation violations with the :scope option, you must create a uniqueness index on both database columns. For more information about multi-column indexes, see the MySQL manual, or examples of unique constraints related to a group of columns in the PostgreSQL manual.

There is also a :case_sensitive option that can be used to specify whether the unique constraint is case sensitive or not. The default option is true.

classPerson < ApplicationRecord

  validates :name, uniqueness: { case_sensitive: false }

end

WARNING. Note that some databases are configured to do case-sensitive searches anyway.

The default error message is “has already been taken”.

validates_with

This helper passes the entry to a separate class for validation.

class GoodnessValidator < ActiveModel::Validator

  def validate(record)

    if record.first_name == “Evil”

      record.errors[:base] << “This person is evil”

    end

  end

end

classPerson < ApplicationRecord

  validates_with GoodnessValidator

end

NOTE: Errors added to record.errors[:base] refer to the state of the record as a whole, not to a particular attribute.

The validates_with helper accepts a class or list of classes to use in validation. There is no default error message for validates_with. You must manually add errors to the errors collection of an entry in the validator class.

In order to use the validate method, it is necessary to have the record parameter defined, which is the record being validated.

Like all other validations, validates_with accepts :if , :unless and :on options. If you pass any other options, they will be passed to the validator class as options:

class GoodnessValidator < ActiveModel::Validator

  def validate(record)

    if options[:fields].any?{|field| record.send(field) == “Evil” }

      record.errors[:base] << “This person is evil”

    end

Validation errors in Ruby on Rails

We’ll look at validation errors in more detail in the Dealing with Validation Errors section.

errors.details

To check which validation has failed on an invalid attribute, errors.details[:attribute] can be used. It returns an array of hashes with the key :error to get the validator symbol:

classPerson < ApplicationRecord

  validates :name, presence: true

end

>>person = Person.new

>> person.valid?

>> person.errors.details[:name] # => [{error: :blank}]

Using details with your own validator is covered in Dealing with Validation Errors.

Validation helpers

Active Record offers many predefined validation helpers that you can use right inside your class definitions. These helpers provide general validation rules. Each time the validation fails, an error message is added to the object’s errors collection, and the message is associated with the attribute that was to be validated.

Each helper accepts an arbitrary number of attribute names, so you can add validations of the same kind to multiple attributes in one line of code.

They all take :on and :message options that specify when the validation should be run and what message should be added to the errors collection if it fails. The :on option takes one of the values ​​:create or :update. Each validation helper has its own default error message. These messages are used if the :message option is not specified. Let’s take a look at each of the available helpers.

acceptance

This method checks that a checkbox in the user interface was clicked when the form was submitted. Typically used when the user needs to agree to your app’s terms of use, confirm that some text has been read, or some other similar concept.

classPerson < ApplicationRecord

  validates :terms_of_service, acceptance: true

end

This check will only be executed if terms_of_service is not nil. For this helper, the default error message is “must be accepted”. You can send an arbitrary message using the message option.

classPerson < ApplicationRecord

  validates :terms_of_service, acceptance: { message: ‘must be accepted’ }

end

It can also receive an :accept option that specifies the allowed values ​​that should be considered accepted. The default is “1”, but you can change it.

classPerson < ApplicationRecord

  validates :eula, acceptance: { accept: [‘TRUE’, ‘accepted’] }

end

This validation is very specific to web applications and its acceptance does not need to be written anywhere in the database. If you don’t have a field for it, the helper will just create a virtual attribute. If the field exists in the database, the accept option must be set to true or else this validation will fail.

validates_associated

This helper can be used when your model has relationships with other models that also need to be validated. When you try to save your object, the valid? method will be called. for each of the related objects.

class Library < ApplicationRecord

  has_many:books

  validates_associated :books

end

This validation works with all types of links.

CAUTION: Don’t use validates_associated on both ends of your associations, they will call each other in an endless loop.

For validates_associated , the default error message is “is invalid”. Note that each related object has its own collection of errors; errors are not added to the calling model.

confirmation

This helper can be used if you have two text fields from which you want to get completely identical content. For example, you want to verify your email address or password. This validation creates a virtual attribute whose name is the name of the field being confirmed, with “_confirmation” appended.

classPerson < ApplicationRecord

  validates :email, confirmation: true

end

In your view template you need to use something like this

<%= text_field :person, :email %>

<%= text_field :person, :email_confirmation %>

This check is only performed if email_confirmation is non-nil. To require confirmation, you need to add another check for the existence of the checked attribute (we will look at presence a bit later):

classPerson < ApplicationRecord

  validates :email, confirmation: true

  validates :email_confirmation, presence: true

end

There is also a :case_sensitive option which is used to determine if the confirmation constraint should be case sensitive. This option defaults to true.

classPerson < ApplicationRecord

  validates :email, confirmation: { case_sensitive: false }

end

The default error message for this helper is “doesn’t match confirmation”.

exclusion

This helper validates that attribute values ​​are not included in the specified set. In fact, this set can be any enumerable object.

The exclusion helper has a :in option that receives a set of values ​​that should not be accepted by the attributes being checked. The :in option has an alias :within which is used for the same purpose. This example uses the :message option to show you how to include an attribute value. See the message documentation for all message argument options.

The default error message value is “is reserved”.

format

This helper validates attribute values ​​by testing them against the specified regular expression, which is specified with the :with option.

class Product < ApplicationRecord

  validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,

    message: “only allows letters” }

end

The default error message value is “is invalid”.

inclusion

This helper validates attribute values ​​for inclusion in the specified set. In fact, this set can be any enumerable object.

class Coffee < ApplicationRecord

  validates :size, inclusion: { in: %w(small medium large),

    message: “%{value} is not a valid size” }

end

The inclusion helper has an :in option that receives a set of values ​​to be accepted. The :in option has an alias :within which is used for the same purpose. The previous example uses the :message option to show you how you can include an attribute value. See the message documentation for all options.

The default error message value for this helper is “is not included in the list”.

length

This helper validates the length of attribute values. It offers a number of options with which you can define length limits in a variety of ways:

classPerson < ApplicationRecord

  validates :name, length: { minimum: 2 }

  validates :bio, length: { maximum: 500 }

  validates :password, length: { in: 6..20 }

  validates :registration_number, length: { is: 6 }

end

The possible options for limiting the length are:

:minimum – attribute cannot be less than a certain length.

:maximum – attribute cannot be more than a certain length.

:in (or :within) – attribute length must be within the specified range. The value of this option must be an interval.

:is – attribute length must be equal to the specified value.

The meaning of the default error message depends on the type of length validation being performed. It is possible to override these messages by using the :wrong_length, :too_long and :too_short options, and %{count} as the place to insert a number corresponding to the length of the limit being used. You can use the :message option to specify the error message.

classPerson < ApplicationRecord

  validates :bio, length: { maximum: 1000,

    too_long: “%{count} characters is the maximum allowed” }

end

Note that the default error messages are plural (ie, “is too short (minimum is %{count} characters)”). For this reason, when :minimum is 1, you should provide your own message or use presence: true instead. When :in or :within have a lower bound of 1, either provide a custom message or call presence before length.

RoR Active Record Validations

This tutorial will teach you how to validate the state of objects before they are sent to the database using Active Record’s validation feature.

After reading the guide, you will know:

How to use the built-in Active Record validation helpers

How to create your own validation methods

How to deal with error messages generated during validation

Overview of validations

Here is an example of a very simple validation:

classPerson < ApplicationRecord

  validates :name, presence: true

end

Person.create(name: “John Doe”).valid? # => true

Person.create(name: nil).valid? # => false

As you can see, our validation lets us know that our Person is not valid without the name attribute. The second Person will not be saved to the database.

Before diving into the details, let’s talk about how validations fit into the big picture of an application.

Why use validations?

Validations are used to make sure that only valid data is saved to your database. For example, it may be important for your application that each user provides a valid email and postal address. Model-level validations are the best way to ensure that only valid data is stored in the database. They are database independent, cannot be bypassed by end users, and are easy to test and maintain. Rails introduces ease of maintenance, provides built-in helpers for common needs, and allows you to create your own validation methods.

There are several ways to validate data before it is stored in your database, including constraints built into the database, client-side validations, and controller-level validations. Briefly about the pros and cons:

Database constraints and/or stored procedures make validation mechanisms dependent on the database, making testing and maintenance more difficult. However, if your database is being used by other applications, database-level validation can safely handle some things (such as uniqueness in loaded tables) that would be difficult to do otherwise.

Client-side validations can be very useful, but generally unreliable when used alone. If they use JavaScript, they may be skipped if JavaScript is disabled in the client browser. However, when combined with others, front-end validations can be a convenient way to provide users with immediate feedback when using your site.

Controller-level validations are tempting to do, but this often leads to cumbersome and difficult testing and maintenance. Whenever possible, keep your controllers ‘skinny’ so your application will be nice to work with in the long run.

Choose them for your specific specific tasks. The general consensus of the Rails team is that model-level validations are the best option in many cases.

When does validation take place?

There are two types of Active Record objects: those that match a row in your database, and those that don’t. When you create a new object, for example using the new method, that object is not yet bound to the database. As soon as you call save, this object will be saved to the appropriate database table. Active Record uses the new_record? to determine if the object is already in the database or not. Consider the following simple Active Record class:

classPerson < ApplicationRecord

end

You can see how it works by looking at the rails console output:

$ bin/rails console

>>p = Person.new(name: “John Doe”)

=> #<Person id: nil, name: “John Doe”, created_at: nil, updated_at: nil>

>>p.new_record?

=> true

>>p.save

=> true

>>p.new_record?

=> false

Creating and saving a new record sends an SQL INSERT operation to the database. An update to an existing record sends an UPDATE SQL operation instead. Validations usually run before these commands are sent to the database. If any of the validations fail, the object is marked invalid and Active Record does not perform the INSERT or UPDATE operation. This helps to avoid storing an invalid object in the database. You can choose to run specific validations when an object is created, saved, or updated.

CAUTION: There are different methods for changing the state of an object in a database. Some methods cause validations, some do not. This means that it is possible to save an object with an invalid status to the database if you are not careful.

The following methods invoke validation, and save the object to the database only if it is valid:

create

create!

save

save!

update

update!

Versions with an exclamation mark (i.e. save!) throw an exception if the entry is invalid. The non-exclamatory versions don’t call: save and update return false, create returns an object.

valid? or invalid?

Before saving an Active Record object, Rails runs your validations. If the validations produce any errors, Rails does not save this object.

You can also run these validations yourself. valid? calls your validations and returns true if no errors were found on the object, false otherwise.

classPerson < ApplicationRecord

  validates :name, presence: true

end

Person.create(name: “John Doe”).valid? # => true

Person.create(name: nil).valid? # => false

After Active Record performs validations, any errors it finds will be available in the errors.messages instance method, which returns a collection of errors. By definition, an object is valid if this collection is empty after validations have been run.

Note that an object created with new does not report errors, even if technically invalid, because validations are only automatically run when the object is saved, as is the case with the create or save methods.

classPerson < ApplicationRecord

  validates :name, presence: true

end

>> p = Person.new

# => #<Person id: nil, name: nil>

>>p.errors.messages

# => {}

>>p.valid?

# => false

>>p.errors.messages

# => {name:[“can’t be blank”]}

>>p=Person.create

# => #<Person id: nil, name: nil>

>>p.errors.messages

# => {name:[“can’t be blank”]}

>>p.save

# => false

>>p.save!

# => ActiveRecord::RecordInvalid: Validation failed: Name can’t be blank

>>Person.create!

# => ActiveRecord::RecordInvalid: Validation failed: Name can’t be blank

invalid? it’s just the opposite of valid?. It runs your validations, returning true if errors have been added to the object and false otherwise.

errors[]

To check whether or not a particular attribute of an object is valid, you can use errors[:attribute] which returns an array with all of the attribute’s errors, when there are no errors for a particular attribute, an empty array is returned.

This method is only useful after the validations have been run, as it only examines the errors collection, but does not invoke the validation itself. It differs from the ActiveRecord::Base#invalid? method described above in that it does not check the validity of the object as a whole. It only checks what errors were found for a particular object attribute.