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.
Quick Rails related note
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 => {} %>