DAVID RICE

Software Developer

+44 (0) 7590 538 303

21 Ormeau Avenue
Belfast, Northern Ireland
BT2 8HD

Inline AJAX form validation plugin for ruby on rails

29 Nov 2006 {View Comments}

While this is a long way off from completed I thought it was quite cool, and didn’t find that many other articles on the topic so here goes;

For those of you who like to see before you do, see the finished product here (edit; movie removed, mail me if you want it put online, thanks).

Update

The code is in git and should be working, let me know if you can’t install the plugin.

script/plugin install git@github.com:davidjrice/ajax_validation.git

The plugin abstracts a couple of things that are common for trying to validate a model with ajax, this is my first plugin so i’m not really sure how to test it but once i figure out… anyway i’m making a couple of assumptions in the plugin so here they are:

  • You are using rails 1.1.6 +
  • It assumes that your model/controller are singular/plural post/posts
  • It assumes you are using the form_for helper
  • It assumes you like ordered list forms :) I know i do.
  • It definitely doesn’t work with dates yet
  • You know how to set up a new rails application

Okay lets start from scratch, fire up your terminal, create a new rails app and follow along;

script/plugin install git@github.com:davidjrice/ajax_validation.git
script/generate scaffold_resource post title:string body:text published_at:datetime

The model

Lets just throw in a couple of validations to see it’s working

class Post < ActiveRecord::Base
    validates_presence_of :title, :body, :published_at
    validates_length_of :title, :in => 3..200
    validates_length_of :body, :minimum => 10
end

The controller

Apart from what’s already created from you, you’ll want to add the following

class PostsController < ApplicationController
  ajax_validation_for :post
  ...
end

The view

To save time i’ll only demonstrate the new.rhtml

<h1>New Post</h1>
<%= error_messages_for :post %>
<%- ajax_validation_form_for(:post, :url => posts_url, :html => {:id => "post_form", :legend => "Post Details"}) do |f| -%>
  <%= f.text_field :title, :label => "Post title", :hint => "between three and two hundred characters" %>        
  <%= f.text_area :body %>
  <%= f.datetime_select :published_at %>   
  <%= submit_tag "Create" %>
<%- end -%>
<%= observe_form :post_form, :url => validate_posts_path, :frequency => 2 %>

As you can see that is using a new method, ajax_validation_form_for… it’s the same as form_for only the fields that are generated are wrapped like the following so if it’s a field like select, or collection select you’ll have to write it by hand as the rjs that is returned depends on some of the fields having the correct ids and supporting elements. oh yeah, and there’s a :hint and :label attribute added to the options for the fields, try it and see.

<li id="post_user_id_item">
    <label for="post_user_id">Author<span class="hint"></span></label>
    <%= f.collection_select :user_id, @users, :id, :display_name %>
    <span id="post_user_id_validation"></span>
</li>

Once you’ve got that all hooked up, you should have something like the example i’ve shown. Although, your mileage may vary :) I look forward to seeing if anyone else finds this useful.

In the above view code, you’ll notice the following line;

<%= observe_form :post_form, :url => validate_posts_path, :frequency => 2 %>

This works because i’ve applied the patch to rails I submitted here http://dev.rubyonrails.org/ticket/6721 however a quick hack to get it to work is to replace the above code with

<%= observe_form :post_form, :url => validate_posts_path, :frequency => 2, :update => {} %>
«