Ruby on Rails ActiveRecord Validations
Tags: rails, activerecord, ruby, database
Published: 2022-07-05 20:29:29

Validations allow us to make sure that data meets a set of requirements before it's saved to the database. You can think of them as rules that our data must follow. It is always a good practice to check the validations from the models to make our models smarter by telling them about what should be considered valid data in the database and also regardless of where we're submitting data from the application, it'll still follow the rules. 

## Built in Validation Methods

Rails provided many inbuilt validation helpers which covers most use cases when you are building an app. Here are the most important ones:

**# validates_presence_of** validates the attribute is not blank

```ruby
validates_presence_of :atrr_name
```

**# Validates_length_of** check length requirements of the attribute

```ruby
validates_length_of :attr_name, :within => 3..40
validates_length_of :attr_name, :is => 40
validates_length_of :attr_name, :minimum => 10, :maximum => 50
```

- `:minimum` - The attribute cannot have less than the specified length.
- `:maximum` - The attribute cannot have more than the specified length.
- `:in` (or `:within`) - The attribute length must be included in a given interval. The value for this option must be a range.
- `:is` - The attribute length must be equal to the given value.

**# Validates_numecality_of** check if the attribute is a number or not

```ruby
validates_numericality_of :height, :greater_than => 3.0
validates_numericality_of :height, :less_than => 100
validates_numericality_of :height, :equal_to => 3.0
validates_numericality_of :height, :greater_than_or_equal_to => 3.0
validates_numericality_of :height, :less_than_or_equal_to => 100
```

- `:greater_than` - Specifies the value must be greater than the supplied value. The default error message for this option is *"must be greater than %{count}"*.
- `:greater_than_or_equal_to` - Specifies the value must be greater than or equal to the supplied value. The default error message for this option is *"must be greater than or equal to %{count}"*.
- `:equal_to` - Specifies the value must be equal to the supplied value. The default error message for this option is *"must be equal to %{count}"*.
- `:less_than` - Specifies the value must be less than the supplied value. The default error message for this option is *"must be less than %{count}"*.
- `:less_than_or_equal_to` - Specifies the value must be less than or equal to the supplied value. The default error message for this option is *"must be less than or equal to %{count}"*.
- `:other_than` - Specifies the value must be other than the supplied value. The default error message for this option is *"must be other than %{count}"*.
- `:in` - Specifies the value must be in the supplied range. The default error message for this option is *"must be in %{count}"*.
- `:odd` - Specifies the value must be an odd number if set to true. The default error message for this option is *"must be odd"*.
- `:even` - Specifies the value must be an even number if set to true. The default error message for this option is *"must be even"*.

**# Validates_inclusion_of** checks to see if an attribute is in a list of choices, and you need to provide it an array or a range for it to look in.
**# Validates_exclusion_of** checks to see if it is not present in the list of choices 

```ruby
validates_inclusion_of :status, :in => ['new', 'created', 'approved', 'deleted']
validates_exclusion_of :status, :in => [55, 66, 77]
```

**# Validates_format_of check** if it matches regex

```ruby
validates_format_of :zipcode, :with => /\d{6}/
```

**# Validates_uniqueness_of** is going to make sure that an attribute is not already in the database.

```ruby
validates_uniqueness_of :user_name, :case_sensitive => false
validates_uniqueness_of :teacher_id, scope: [:semester_id, :class_id]
 # Making sure that a teacher can only be on the schedule once per semester for a particular class.
```

**# Validates_confirmation_of** Encapsulates the pattern of wanting to validate a password or email address field with a confirmation

```ruby

 validates_confirmation_of :user_name, :password
 validates_confirmation_of :email_address,
                              message: 'should match confirmation'
# The added password_confirmation attribute is virtual; it exists only as an in-memory attribute for validating the password. To achieve this, the validation adds accessors to the model for the confirmation attribute.
# NOTE: This check is performed only if password_confirmation is not nil. To require confirmation, make sure to add a presence check for the confirmation attribute:
```

**# Validates_associated** is used to check associations with other models, so it check the validity of the associated model

```ruby
class Library < ApplicationRecord
	has_many :books
	validates_associated :books
end
```

**# Validates_acceptance_of** is typically used when the user needs to agree to your application's terms of service, confirm that some text is read, or any similar concept. This method creates a virtual attribute and it is not saved to the database.

```ruby
validates_acceptance_of :terms_of_service
```

**# Validate multiple parameters** in one go

```ruby
validates :attr_name,
	:presence => boolean,
	:numericality => boolean,
	:length => option_hash,
	:format => {:with => regex},
	:inclusion => {:in => range_or_array},
	:exclusion => {:in => range_or_array},
	:acceptance => boolean,
	:uniqueness => boolean,
	:confirmation => boolean
```

## Custom Validations

Most of the time, the built-in validations that Ruby on Rails gives you, are going to be enough to help you keep your data under control. But every now and then there's some special cases that come up where they're not enough and we'd like to be able to write our own custom validations. Well, Ruby on Rails lets us do that too.

```ruby
validate :custom_method

private

def custom_method
	if test_case
		error.add(:attribute, "error message")
		# You can use :base as attribute name if the error is not specific to an attribute 
	end
end
```

## Skipping Validation

Skipping validations bypasses the data rules that you've established for the application and it should be done with extreme caution because you could actually introduce invalid data into the database and that could have severe consequences to the application.
Here are few ways to do that.

```ruby
record.save(validate: false)
record.update_columns(:name => value) # This directly updates the database
record.update_column(:name, value)
```

When you have an active record relation, you've built up like a relation defined using where clauses to find the record you want, then you can call, update all and provide a hash of values and it will go and do update columns ****on all of those records without actually finding them.

```ruby
relation.update_all(:name => value)
```

> Thanks For Reading, Follow Me For More
> Share your suggestions, doubts and feedback in the comments section!