Clean Validations with Custom Contexts
Active Record validations are well-known and widely used in Rails.
class User < ApplicationRecord
validates :name, presence: { message: "must be given please" }
end
This runs the validation on save
, both when creating a new record or when updating an existing record.
on
option allows control over when to run the validation, commonly used with value of create
or update
class User < ApplicationRecord
belongs_to :club, optional: true
validates :name, presence: { message: "must be given please" }, on: :create
validates :club, presence: { message: "must be given please" }, on: :update
end
This allows creating users without associating them with a Club but enforces the presence of Club on subsequent updates. This pattern is commonly used to allow users to signup with bare minimum form fields and then forcing them to update their profiles with more information on subsequent visits.
Value for the on
option is not limited to create
and update
, we can have our own custom contexts. Like in a multistep form, we can have validations for each of the steps. on
options makes this really easy to do
class User < ApplicationRecord
validate :basic_info, on: :basic_info
validate :education_details, on: :education_details
validate :professional_info, on: :professional_info
private
def basic_info
# Validation for basic info, first_name, last_name, email
end
def education_details
# Validation for education_details
end
def professional_info
# Validation for professional_info
end
end
In the controller
class UsersController < ApplicationController
...
def update_basic_info
@user.assign_attributes(basic_info_params)
@user.save(:basic_info)
end
def update_education_details
@user.assign_attributes(education_details_params)
@user.save(:education_details)
end
def update_professional_info
@user.assign_attributes(professional_info_params)
@user.save(:professional_info)
end
private
def basic_info_params
# strong params
end
def education_details_params
# strong params
end
def professional_info_params
# strong params
end
end
With Rails 5 adding support for multiple contexts, we can use multiple contexts together
@user.save(:basic_info, :professional_info)
This seems pretty neat, let’s go a step further and do this with update_attributes
. In current implementation of Rails,
update_attributes
does not support validation contexts. We can get around this by defining our own custom method
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def update_attibutes_with_context(attributes, *contexts)
with_transaction_returning_status do
assign_attributes(attributes)
save(context: contexts)
end
end
end
In the controller
@user.update_attibutes_with_context({first_name: 'fname'}, :basic_info)
Lastly, we can use with_options
to group multiple validations within a context
with_options on: :member do |member_user|
member_user.validates :club_name, presence: true
member_user.validates :membership_id, presence: true
end
About RemotePanda
RemotePanda is a personalized platform for companies to hire remote talent and get the quality work delivered from the city Pune. The resources in our talent pool are our close network connections. While connecting them with you, we make sure to manage the quality, growth, legalities, and the delivery of their work. The idea is to make remote work successful for you. Get in touch with us to learn why RemotePanda is the best fit solution for your business requirements.