Validation form in Ruby on Rails with jquery.validate()

In this post you will see how to do client side validation with jQuery in a Ruby on Rails application. The post assumes you have some knowledge of Ruby on Rails views and jQuery selectors.

We will validate a typical user registration form using the jQuery Validation plugin.

>>>register form<<<

<% form_for @user do |f| %>
<%= f.error_messages %>

<%= f.label :email %>
<%= f.text_field :email %>

<%= f.label :password %>
<%= f.password_field :password %>

<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>

<%= f.submit “Register” %>

<% end %>

<%= link_to “Cancel”, :back %>

which looks like this:

<form id="new_user" action="" method="post"><label for="user_email">Email</label>
<input id="user_email" type="text" name="user[email]" size="30" />
<label for="user_password">Password</label>
<input id="user_password" type="password" name="user[password]" size="30" />
<label for="user_password_confirmation">Password confirmation</label>
<input id="user_password_confirmation" type="password" name="user[password_confirmation]" size="30" />
<input id="user_submit" type="submit" name="commit" value="Register" />
</form>

Notice that rails automatically added the id “new_user” for the form and provided ids for all elements of the form. This will come in handy a little later.

When this form is submitted the controller creates a new user model object, validates it using code in user.rb and saves the entry in the database. Relying on server-side validation done through the model is fine, but we can improve the usability of the application through client side validation.

Here are some of the things we want to check on the client side:

  1. All fields have been filled out
  2. The email is a valid email field.
  3. The password is at least 6 characters long
  4. The password and password_validation field match
  5. The email is not already in use

Loading up jQuery in the Application

Download the jQuery library .

Download the jQuery validation plugin.

Save the two plugins in rails_app/app/assets/javascripts/

Load up the plugins in rails_app/app/assets/javascripts/applications.js:

//= require jquery

//= require jquery.validate

Writing the Validation

The jQuery validation plugin is really easy to set up. Once the DOM is loaded we will add validation requirements to each fields in the form using the validate() function. We reference the fields through their name attribute.

<script>
$(document).ready(function () {
$(“#new_user”).validate({
debug: true,
rules: {
“user[email]“: {required: true, email: true},
“user[password]“: {required: true, minlength: 6},
“user[password_confirmation]“: {required: true, equalTo: “#user_password”}
}
});
});
</script>

The code is self explanatory. One thing that is specific to using jQuery validation with Rails forms, is that Rails adds field information to a hash map using form names like user[email]. Because of the square brackets we need to escape the form names used in the validate() function by surrounding them with quotes.

The debug:true option helps when writing validation rules because it makes sure that the form doesn’t get submitted even if there are syntax errors in the validation rules. Once you tested that the rules work, you can remove that option.

Here is the list of validation options available with the jQuery validation plugin.

Sprinkle some AJAX fairy dust with remote

Okay, so we’re checking that all the fields are filled out, etc., but the interesting part is checking whether or not the email address has already been used to create an account. To do this we will send an AJAX request to a rails action (let’s call it check_email) that will tell us if the given email address is already in use. Instead of responding with a regular html view, check_email responds with javascript code that is executed on the client side. To do this jQuery provides us with a special validation method called remote().

First let’s add the validation rule to the email field

// in application.js
<script>
$(document).ready(function () {
$(“#new_user”).validate({
debug: true,
rules: {
“user[email]“: {required: true, email: true, remote:”/users/check_email” },  //added this
“user[password]“: {required: true, minlength: 6},
“user[password_confirmation]“: {required: true, equalTo: “#user_password”}
}
});
});
</script>

The remote function will send a GET request to

/users/check_email?user[email]=user@email.com

thus passing the email as a parameter to our action. The HTTP Accept parameter of the request is set to "text/javascript". This means the application is expecting a response in javascript format (actually the docs mention JSON) from the server. The action must use the email to determine if the email is already in use, and return true or false (no quotes).

Now let’s write the action and view and set it up in the routes.rb file.

# in users_controller.rb
def check_email
  @user = User.find_by_email(params[:user][:email])

  respond_to do |format|
   format.json { render :json => !@user }
  end
end

# in routes.rb

map.check_email “users/check_email”, :controller => “users”, :action => “check_email”
map.resources :users

If the user object exists for the given email, then the email is not available so the response is false and the validator will ask the user to change the email.

The remote function is a very powerful tool, because it allows us to combine server side and client side validation, thus providing better usability which makes our website visitors happy!

Resources

jQuery: http://www.jquery.com

jQuery Validation Plugin: http://plugins.jquery.com/project/validate

jQuery Validation Plugin Reference: http://docs.jquery.com/Plugins/Validation

Leave a comment