Rails Validations and Forms

jordy garcia
5 min readMay 18, 2021

--

In this article, I will explain to you more about basic validations, error messages and forms.

So let’s start by creating a User model!

$ rails g model User name email age:integer

And now we need to migrate our model into our database.

$ rails db:migrate

To create the controller follow the steps in this article:

Basic Rails API | by jordy garcia | May, 2021 | Medium

So let’s start with our validations, go to app/models/user.rb, and write…

app/models/user.rbclass User < ApplicationRecord  validates :name, presence: true, length: { maximum: 15}end

This will validate only :name, it will check if it’s not empty and that the maximum length is fifteen otherwise it will throw us an error!

Btw if you only wants to validate the presence you could write it like this.

validates_presence_of :name

And the same goes for email and age, of course when using an integer you can’t use length but should use “numericality”, let me give you an example.

app/models/user.rbclass User < ApplicationRecord  validates :name, presence: true, length: { maximum: 15}
validates_presence_of :email
validates :age, numericality: { greater_than: 0 }
end

So here we would add a validation to see if the age is greater than zero.

Great job! We now have a user model with validations that would prevent us from creating users without a name, email or age.

Let’s create our form in app/views/users/_form.html.erb, did you see how I wrote “_form.html.erb”, with an underscore in front? That is how we create partial files, partial files are files we can render anywhere, I will show you later! The reason why I create the form in a partial file is so we can use the same form for “create” and “update”.

app/views/_form.html.erb<%= form_with model: @user do |form| %>
<%= form.label :name %>
<%= form.text_field :name %>
<%= form.label :email %>
<%= form.email_field :email %>
<%= form.label :age %>
<%= form.number_field :age %>
<%= form.submit %><% end %>

So now we just paste this line in our app/views/users/new.html.erb and app/views/users/edit.html.erb files.

<%= render "form" %>

This will render our form, so you just write “render” followed by the path where the file is located. You can see how we write just “form” instead of “_form.html.erb” that is again because rails is smart and know exactly what you mean by writing just “form”

So let us start from the first line where I used “form_with model: @user”, the @user is the class variable we defined in our controller which looks like.

app/controllers/users_controller.rbdef new
@user = User.new
end
def edit
@user = User.find(params[:id])
end

So if we want to create a user we will have the form_with model: using the new method and when we want to edit a user we will use the edit method, which in this case is looking for a user through our params, and will fill in the form fields automatically with the @user values. More info about the controller and params in this article.

Basic Rails API | by jordy garcia | May, 2021 | Medium

So we got the model part out of the way let’s now focus on the form itself! I wrote after form_with model: @user “do |form|” this will make it easier to connect all our text_fields and labels to our model @user.

form.label :name

This will be the label for our name which will be the default “Name”, if you want to change that you simply do it like this.

form.label :name, "Write your name:"

You could also add a class and modify your label with some CSS.

form.label :name, "Write your name:", class: "label-class"

Of course, you can change “label-class” to any preferred name.

Then we got the text field.

form.text_field :name 

Whatever value is written inside that text field will be assigned to the :name if it passes the validations we set up earlier.

Here you could also add a class in the same way as before.

form.text_field :name, class: "text-field-class"

And the same goes for email and age.

The default of form.submit, will create a button called “Create User” when on the new.html.erb page and “Update User” when on the edit.html.erb file.

Cool! We just created a form and connected it with our database in less than five minutes!

So now when we try to create a User without a name we get an error… ERR or not? So it validates whether a user can be created or updated but it doesn’t show us any error messages… why?

That is because we need to render those messages in our form! I will show you first how our form will look only for the name and after I will show the whole form.

app/views/users/_form.html.erb<%= form_with model: @user do |form| %><% @user.errors.full_messages_for(:name).each do |message| %>
<%= message %>
<% end %>
<%= form.label :name, "Write your name:", class: "hello" %>
<%= form.text_field :name %>
------<% end %>

So like you can see I wrote “@user.errors.full_messages_for(:name)”, let’s break it down! @user is our model, so we select the errors from our model, and then select the full messages for name, if you would just write “full_messages” without writing “for(:name)” it would show you all the error messages on top, so if you prefer all the errors at the beginning of your form you can write it without “for(:name)”. Just like this…

<% @user.errors.full_messages.each do |message| %>
<%= message %>
<% end %>

Now that we have selected the error messages just for our name validation we can use our each method to display each error message in our form. So now our form should look like this.

app/views/users/_form.html.erb<%= form_with model: @user do |form| %><% @user.errors.full_messages_for(:name).each do |message| %>
<%= message %>
<% end %>
<%= form.label :name, "Write your name:", class: "hello" %>
<%= form.text_field :name %>
<% @user.errors.full_messages_for(:email).each do |message| %>
<%= message %>
<% end %>
<%= form.label :email %>
<%= form.text_field :email %>
<% @user.errors.full_messages_for(:age).each do |message| %>
<%= message %>
<% end %>
<%= form.label :age %>
<%= form.number_field :age %>
<%= form.submit %>
<% end %>

Like you can see I just changed the symbol :name in full_messages_for(:name) to :email and :age, and it will only show the error messages for those attributes.

Yay, you’re on rails! Or better said, “Yay you have error messages!”

But now when we don't fill in the name and try to submit we get the error “Name can’t be blank” which is a default message of Rails, thank you rails but we rather have our personalized and funny error messages!

So let’s go back to our app/models/user.rb file.

app/models/user.rbclass User < ApplicationRecordvalidates :name, presence: true, length: { maximum: 15, message:   "Name shouldn't be longer than 15 characters come on?"}validates_presence_of :email, message: "Are you sure this is an email?"validates :age, numericality: { greater_than: 0, message: "User should be born to be able to get created!" }end

So like you can see we just write after our validation “message:” and your message. If you now try to create a user it will show you these funny error messages.

Yay funny personalized error messages! So now you are ready to create your own forms with cool and funny error messages!

Thanks for reading my article and hopefully you’re next form will be like “The Jackson 5” used to say:

“Easy as one, two, three
Ah, simple as Do Re Mi
ABC, one, two, three”

--

--

jordy garcia

Full-Stack Web Developer. Ruby on Rails, React, Redux. JavaScript, Improving open-source projects, one commit at a time.