Rails - Validation

rails

What is inside app/models/article.rb?

class Article < ActiveRecord::Base
end

There isn't much to this file - but note that the Article class inherits from ActiveRecord::Base. Active Record supplies a great deal of functionality to your Rails models for free, including basic database CRUD (Create, Read, Update, Destroy) operations, data validation, as well as sophisticated search support and the ability to relate multiple models to one another.

How to validate your data?

Rails includes methods to help you validate the data that you send to models. Open the app/models/article.rb file and edit it:

class Article < ActiveRecord::Base
  validates :title, presence: true,
                    length: { minimum: 5 }
end

These changes will ensure that all articles have a title that is at least five characters long. Rails can validate a variety of conditions in a model, including the presence or uniqueness of columns, their format, and the existence of associated objects. Validations are covered in detail in Active Record Validations

With the validation now in place, when you call @article.save on an invalid article, it will return false. If you open app/controllers/articles_controller.rb again, you'll notice that we don't check the result of calling @article.save inside the create action. If @article.save fails in this situation, we need to show the form back to the user. To do this, change the new and create actions inside app/controllers/articles_controller.rb to these:

def new
  @article = Article.new
end

def create
  @article = Article.new(article_params)

  if @article.save
    redirect_to @article
  else
    render 'new'
  end
end

private
  def article_params
    params.require(:article).permit(:title, :text)
  end

The new action is now creating a new instance variable called @article. The reason why we added @article = Article.new in the ArticlesController is that otherwise @article would be nil in our view, and calling @article.errors.any? would throw an error (see below).

Notice that inside the create action we use render instead of redirect_to when save returns false. The render method is used so that the @article object is passed back to the new template when it is rendered. This rendering is done within the same request as the form submission, whereas the redirect_to will tell the browser to issue another request.

If you reload http://localhost:3000/articles/new and try to save an article without a title, Rails will send you back to the form, but that's not very useful. You need to tell the user that something went wrong. To do that, you'll modify app/views/articles/new.html.erb to check for error messages:

<%= form_for :article, url: articles_path do |f| %>
  <% if @article.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@article.errors.count, "error") %> prohibited
      this article from being saved:</h2>
    <ul>
    <% @article.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
  <% end %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>

<%= link_to 'Back', articles_path %>

A few things are going on. We check if there are any errors with @article.errors.any?, and in that case we show a list of all errors with @article.errors.full_messages. pluralize is a rails helper that takes a number and a string as its arguments. If the number is greater than one, the string will be automatically pluralized.

What is field_with_errors?

Rails automatically wraps fields that contain an error with a div with class field_with_errors. You can define a css rule to make them standout.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License