Form validations in Ruby On Rails Application.
Tags: ruby, rails, tutorial, validation
Published: 2022-09-02 00:30:25

In this article, we will learn how to manage server-side and client-side form validations according to our requirements and how we manage this at the application level.

Recently I have worked on form-validation systems in a couple of modern Rails apps, and I learned a few things along the way I would like to share.

## Example and source code

I prepared a [demo project here](https://github.com/kananinirav/rails-form-validations-example). It’s a Rails 5.2 application with a scaffold generated for managing users. A user has 2 attributes: name and email. The validations are:

* Both name and email are required: to exercise client-side validations.

* The email has to be unique, to exercise server-side validations.

## Server-side validations with Rails

I love [Rails validations](https://guides.rubyonrails.org/active_record_validations.html). They are a powerful mechanism to capture your domain model validation rules, which are essential components of any app. For our example, we can capture the model constraints with something like this:

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

A common Rails pattern for dealing with form errors is re-rendering the form with the invalid model carrying the errors to inform about them:

```
class UsersController < ApplicationController
  ...
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user, notice: 'User was successfully created.'
    else
      render :new
    end
  end

  def update
    if @user.update(user_params)
      redirect_to @user, notice: 'User was successfully updated.'
    else
      render :edit
    end
  end
  ...
end
```

If you are going to use this approach there is a problem with it how we can show errors next to fields.

For dealing with the problem, you can customize ActionView::Base.field_error_proc which is a block of code that Rails uses to render fields with errors. By default, it will wrap them in a div.field_with_errors tag. You can configure it to render the same structure as client-side validations. In our example:

 1. Invalid fields are marked with a .invalid class

 2. Information about the error is shown in a p.error element next to the invalid field.

```
# Place this code in a initializer. 
# E.g: config/initializers/form_errors.rb
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance_tag|
  fragment = Nokogiri::HTML.fragment(html_tag)
  field = fragment.at('input,select,textarea')

  html = if field
           field['class'] = "#{field['class']} invalid"
           html = <<-HTML
              #{fragment&.to_s}
              <p class="error">#{instance_tag&.error_message&.first}</p>
           HTML
           html
         else
           html_tag
         end

  html.html_safe
end

```

CSS — You can customize it according to your requirements.

    # app/assets/stylesheets/application.css

    .field p{
      margin-top: 0;
    }

    .error{
      color: red;
    }

    .invalid{
      border: 1px solid red;
    }

The new form validations look like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/olcqa7jegciwwp9l8s3s.gif)

we will have a form that validates duplicated emails consistently with our system.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r9x60tx2xyxwwm0i5prr.gif)

What I love about this approach is that you don’t need to do any extra work to show model errors in your forms. Just add model validations.

## Client side validations with HTML 5

Form validations are captured in the HTML markup. You can read a [nice reference here](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation). For our purposes, we will modify the generated scaffold form to use them:

    <%= form.text_field :name, required: true %>
    ...
    <%= form.email_field :email, required: true %>

With this in place, the browser won’t allow submitting invalid data, and it will show an error message based on the kind of validation.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/62l9dcgmxzbe8ip67zo4.gif)

This works but you probably won’t love how it looks, and you can’t style it at all.

I like server-side validation because it is not dependent on the client machine or browser or OS.

**Conclusions**

The discussed approach works great because, with a little bit of infrastructure in place, it lets you express your form validations very succinctly while being robust and comprehensive:

* Use HTML5 form validations when they cover the validation you need

* Use model validations in your server. This is something you want to do nevertheless.

If this guide has been helpful to you and your team please share it with others!