Understanding Ruby on Rails ActiveRecord Validations
Tags: videos, webdev, rails, ruby
Published: 2019-02-28 23:31:18

---
title: Understanding Ruby on Rails ActiveRecord Validations
published: true
tags: Videos,Web Development,rails, ruby
canonical_url: https://web-crunch.com/understanding-ruby-on-rails-activerecord-validations/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/v0cdpt34778j9w5uw9n7.jpg
---

Data is a great thing but the wrong data can be very very bad. Luckily, if you’re a Ruby on Rails programmer you have a nice API of ActiveRecord validation helpers at your disposal.

This guide is an exploration of common and not so common ActiveRecord validations in a given Ruby on Rails application. Use it to help keep your databases happy!

{% youtube c3hoXWO_6ao %}

### Why use validations?

To ensure only valid data is saved to your database. On top of clientside validation, model-level validations provide an extra layer of security for any and all form fields within a Ruby on Rails application.

You can provide validations in a variety of levels but all have their strengths and weaknesses.

- **Database constraints** – Unique constraints at the database level allows for no duplicate fields or columns if you require. This can go much deeper than just uniqueness. i.e. Default values, non-nil constraints, ranges, etc…
- **Client-side validation** – These are useful visually and provide better user experience but are often more unreliable. I’d almost always provide a backup plan using this approach as one should.
- **Model Level** (Rails) – What we are talking about now!
- **Controller Level** (Rails) – Tempting to use but more difficult to test and maintain. It’s a convention/best-practice to keep your controllers as light as possible. 

### When does validation actually occur?

Straight from the ruby on rails documentation:

> There are two kinds of Active Record objects: those that correspond to a row inside your database and those that do not. When you create a fresh object, for example using the `new` method, that object does not belong to the database yet. Once you call `save` upon that object it will be saved into the appropriate database table. Active Record uses the `new_record?` instance method to determine whether an object is already in the database or not.

Creating a new Active Record class grants us an opportunity to use a `new_record?` method to figure this all out.

```ruby
class Article < ApplicationRecord
end
```

In doing so we can hit `rails console` to pinpoint the process.

```bash
$ rails console

>> article = Article.new(title: "My Article")
=> #<Article id:nil title: "My Article", created_at: nil, updated_at: nil>
>> article.new_record?
=> true
>> article.save
=> true
>> article.new_record?
=> false
```

Actually calling `save` is what commits it to the database and behind the scenes creates the necessary `SQL` statements to do so. As a result, validations are typically run before sending data to the database entirely.

The following methods envoke validations upon use:

- `create`
- `create!`
- `save`
- `save!`
- `update`
- `update!`

> The bang versions (e.g. `save!`) raise an exception if the record is invalid. The non-bang versions don’t: `save` and `update` return `false`, and `create` just returns the object.

### Methods that skip validations

Using any of the following will skip validations entirely. **Use with caution on valuable data!**

- `decrement!`
- `decrement_counter`
- `increment!`
- `increment_counter`
- `toggle!`
- `touch`
- `update_all`
- `update_attribute`
- `update_column`
- `update_columns`
- `update_counters`

## Validation helpers

What I love about Ruby on Rails is the bundled goodness you get for doing pretty hard things. Validation helpers are one of those things that make me feel warm and cozy when deploying a new app out in the wild. This provides a lot of support for a large range of data you may be collecting from the client-side.

Each helper accepts a `:on` and `:message` option. These options define when the validation should be run and what message should be added to an `errors` collection if it fails (you can use these to help inject what’s wrong inside your views so the user knows what to change/alter).

There are a ton of validation helpers, below are some of my most used. Please check out the [guide on active record validations](https://guides.rubyonrails.org/active_record_validations.html) for more use-cases.

### Confirmation

Useful for validating when two text fields need to have the same entry. Think of an email confirmation for example.

```ruby
class User < ApplicationRecord
  validates :email, confirmation: true
end
```

Now in your view you can have two fields:

```ruby
<%= text_field :user, :email %>
<%= text_field :user, :email_confirmation %>
```

One gotcha here is that this validation only performs if the `presence` option is set to true in the model as well.

So the `User` model gets an update:

```ruby
class User < ApplicationRecord
  validates :email, confirmation: true
  validates :email_confirmation, presence: true  
end
```

### Exclusion

If you need to reserve any words or make sure a given entry is unique use `exclusion`.

```ruby
class Profile < ApplicationRecord   
  validates :username, exclusion: { in: %w(username1 username2 username3), message: "%{value} has already been taken." }
end
```

Notice how I used `:message` here as well. This is provided on all validation helpers.

You can also use `inclusion` in the opposite manner. See the docs for more info!

### Format

Formatting strings are sometimes ideal for your app. You can use regular expressions within validations to alter whatever you’re after.

```ruby
class Plan < ApplicationRecord
  validates :plan_type, format: { with: /\A[a-zA-Z]+\z/, message: "Plans can only inlude letters"}
end
```

### Length

I use this one all the time to put a constraint on the character length of a given field.

```ruby
class User < ApplicationRecord
  validates :name, length: { minimum: 5 } # sets a minimum
  validates :bio, length: { maximum: 500 } # sets a maximum
  validates :handle, length: { in: 5..16 } # provide a range
end
```

Feel free to personalize the messages with `:message` here as well. The following are all available to hook into to customize the message.

- `wrong_length`
- `too_long`
- `too_short` 

Example

```ruby
class User < ApplicationRecord
    validates :bio, length: { maximum: 800, too_long: "%{count} characters is the maximum." }
end
```

### Presence

This is probably the most widely used helper in my tool bag. Presence checks that fields are **not** empty.

```ruby
class User < ApplicationRecord
  validates :name, :email, presence: true
end
```

You can also test an association exists on models

```ruby
class Article < ApplicationRecord
  belongs_to :user
  validates :user, presence: true # looks for a user_id field on the article
end
```

On the opposing model, you can do the same with one catch called `inverse_of`

```ruby
class User < ApplicationRecord
  has_many :articles, inverse_of: :user
end
```

### Uniqueness

Maybe you want unique usernames on your app? Uniqueness helps with that.

```ruby
class User < ApplicationRecord
  validates :username, uniqueness: true, { message: "Username already taken" }
end
```

This actually searches the `User` table for existing records to determine `uniqueness`

You can go further and limit the `uniqueness` down to a `scope`.

```ruby
class User < ApplicationRecord
  validates :plan, uniqueness: { scope: :year, message: "can only update one per year"}
end
```

## Conditional Validations

Sometimes you only need to validate within given conditions. You can perform conditionals using an approach like the following.

```ruby
class Purchase < ApplicationRecord
  validates :card_number, presence: true, if: :paid_with_card?

  def paid_with_card?
    payment_type == "card"
  end
end
```

Need to group multiple conditions? You can do that

```ruby
class User < ApplicationRecord
  with_options if: :is_admin? do |admin|
    admin.validates :location, length: { minimum: 10 }
    admin.validates :job_title, presence: true
  end
end
```

## Custom Methods

Sometimes the helpers aren’t enough and you might need something more custom. You can create your own methods that do some validations you roll yourself.

```ruby
class Invoice < ApplicationRecord
    validate :active_subscriber, on: :create

    def active_customer
        errors.add(:customer_id, "is not active") 
        unless subscriber.active?
    end
end
```

Note here I’m validating this method using the `:on` option which lets you determine where to initialize the validation. In this case I chose `:create`.

You can also hook into the `errors` collection as I have to amend what outputs on the client-side if you need to. We don’t have the `:message` on custom methods in this case. [Read more about errors](https://guides.rubyonrails.org/active_record_validations.html#working-with-validation-errors).

### Final Words

Hopefully, validations have opened some ideas for you to make your app more constrained (in a good way). Using Ruby on Rails and all of its facets allows for safe data to enter any database of your choosing. From CSRF tokens to database-level validations, there are endless ways to enhance your app can remain calm about the data coming in.

### Shameless Plug!

If you liked this post, I have more videos on [YouTube](https://youtube.com/c/webcrunch) and here on my [blog](https://web-crunch.com). Want more content like this in your inbox? [Subscribe to my newsletter](https://web-crunch.com/subcribe) and get it automatically.

#### Check out my course

[  
 ![https://i2.wp.com/i.imgur.com/KIaaJEB.jpg?ssl=1](https://i2.wp.com/i.imgur.com/KIaaJEB.jpg?ssl=1)  
](https://hellorails.io)

![☝](https://s.w.org/images/core/emoji/11/72x72/261d.png) Want to learn Ruby on Rails from the ground up? Check out my upcoming course called [Hello Rails](https://hellorails.io).

The post [Understanding Ruby on Rails ActiveRecord Validations](https://web-crunch.com/understanding-ruby-on-rails-activerecord-validations/) appeared first on [Web-Crunch](https://web-crunch.com).