0
0
RailsHow-ToBeginner · 3 min read

How to Display Validation Errors in Form in Ruby on Rails

In Ruby on Rails, display validation errors in a form by using the form_with helper combined with model.errors.full_messages to show error messages. You can use form_with along with custom code to list errors above the form fields.
📐

Syntax

Use form_with model: @model to create a form bound to a model instance. Inside the form, check @model.errors.any? to see if there are errors. Use @model.errors.full_messages to get an array of error messages to display.

This pattern helps show validation errors after a form submission fails.

erb
<%= form_with model: @user do |form| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
      <ul>
        <% @user.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div>
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>

  <div>
    <%= form.label :email %>
    <%= form.email_field :email %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>
💻

Example

This example shows a simple user form that displays validation errors if the user submits invalid data, such as missing name or email.

ruby,erb
# app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
  validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
end

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to root_path, notice: "User created successfully"
    else
      render :new
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

# app/views/users/new.html.erb
<%= form_with model: @user do |form| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
      <ul>
        <% @user.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div>
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>

  <div>
    <%= form.label :email %>
    <%= form.email_field :email %>
  </div>

  <div>
    <%= form.submit "Create User" %>
  </div>
<% end %>
Output
<form action="/users" method="post"> <div id="error_explanation"> <h2>2 errors prohibited this user from being saved:</h2> <ul> <li>Name can't be blank</li> <li>Email can't be blank</li> </ul> </div> <div> <label for="user_name">Name</label> <input type="text" name="user[name]" id="user_name" /> </div> <div> <label for="user_email">Email</label> <input type="email" name="user[email]" id="user_email" /> </div> <div> <input type="submit" value="Create User" /> </div> </form>
⚠️

Common Pitfalls

  • Forgetting to check @model.errors.any? before displaying errors can cause empty error blocks.
  • Not rendering the form with the invalid model instance after a failed save means errors won't show.
  • Using form_tag instead of form_with model: loses automatic error binding.
  • Not permitting parameters correctly in the controller can cause validation to fail silently.
erb
<!-- Wrong: Not checking errors -->
<%= form_with model: @user do |form| %>
  <div id="error_explanation">
    <ul>
      <% @user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
  <!-- form fields -->
<% end %>

<!-- Right: Check errors before showing -->
<%= form_with model: @user do |form| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <ul>
        <% @user.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
  <!-- form fields -->
<% end %>
📊

Quick Reference

  • Use form_with model: @model to bind form to model instance.
  • Check @model.errors.any? before displaying errors.
  • Use @model.errors.full_messages to get readable error messages.
  • Render the form with the invalid model instance after failed save to keep errors visible.
  • Permit parameters correctly in the controller to avoid silent failures.

Key Takeaways

Always use form_with model: @model to bind forms to models for automatic error handling.
Check @model.errors.any? before showing error messages to avoid empty error blocks.
Display errors using @model.errors.full_messages inside the form for clear feedback.
Render the form with the invalid model instance after a failed save to keep errors visible.
Permit parameters properly in the controller to ensure validations run correctly.