Vinícius B. Alonso

Vinícius B. Alonso

Developer

© 2019

Back

Multistep Validations with Active Model

This is the first blog post in a series explaining the topics of my talk Don’t Rewrite your framework at TropitalRails.

Imagine the following scenario: You have an e-commerce. Customers should create an account.

class Customer < ApplicationRecord
  validates :name, :email, :password, :address_street, :address_city, presence: true
end

Then, you receive a request to make the address information optional at first, but only when the customer buys something. Basically, you need to have different validation steps in the same model. How would you do that? For these cases, ActiveModel provides context validations.

class Customer < ApplicationRecord
  validates :name, :email, :password, presence: true, on: :create
  validates :address_street, :address_city, presence: true, on: :account_finish
end

Now we have two different contexts create and account_finish. In the example below we try to create a customer without the address informations. The validation will pass because we are using the create context.

customer = Customer.new(name: 'John', email: 'john@google.com', password: '123')
customer.valid?
# => true

customer.save
# => true

In the next example, we try to finish the account without the address informations. The validation will fail, because we are using the account_finish context.

customer.valid?(:account_finish)
# => false

customer.save(context: :account_finish)
# => false

We can fill the address informations and try again.

customer.address_street = "1105 West Peachtree St"
customer.address_city = "Atlanta"
customer.valid?(:account_finish)
# => true

customer.save(context: :account_finish)
# => true

As we saw in this short post, context validations can be very useful. They allow us to have different validation steps in the same model. Rails also provides a context for update, similar to create.

References