1 0 Archive | tutorials RSS feed for this section
post icon

Handling Validation Errors using Ajax Requests in Rails

After spending about 6 hours reserching how to handle errors when using ajax requests to create, update and do other actions in Ruby on Rails I got fed up and started doing it on my own, with a little help from Agile Web Development with Rails.

I spent countless hours looking through google and found nothing I liked, and this is why I’m writing this post. I also found nothing that showed all the code, from view to controller to js. So I’ll try and include everything here.

First background on what I wanted to do… I have an index.html.erb file that loops through an object that contains a bunch of stuff. What I wanted was:

  1. Have a form_remote_for at the bottom of this list that would do an Ajax.Request
  2. Have the new form values save to the database
  3. Print the new data to the bottom of the current list
  4. And handle any errors so the user would know wtf was going on

Ryan Bates has a sweet railscast screencast showing how to implement… well everything except the error handling. I’m just going to make it really simple just so you get an idea.

My index.html.erb file:

<table id="teams">
 <tr>
  <th>Team name</th>
  <% if logged_in? -%>
   <th>Action</th>
  <% end -%>
  </tr>
  <% for @team in @teams -%>
   <tr>
    <td><%= link_to @team.name, league_team_path(@league.id, @team.id) %></td>
    <% if logged_in? -%>
     <td>
      <%= link_to_remote image_tag('file_remove.png'), :url => team_path(@team.id), :method => :delete, :confirm => "Are you sure?" %>
      <%= link_to image_tag('file_edit.png'), edit_team_path(@team.id) %>
     </td>
    <% end -%>
   </tr>
  <% end -%>
</table>
<% if logged_in? -%>
 <div class="ajax_form">
  <% form_remote_for :team, :url => teams_path do |f| -%>
   <p id="team_name_para">
    <label id="team_name_label" for="team_name">Team name:</label>
    <%= f.text_field :name, :class => "large_set_width", :value => "" %>
    <button class="form_submit" type="submit"><span>Save</span></button>
   </p>
  <% end -%>
 </div>
<% end -%>

This is pretty basic, I just loop through all teams and print them out into a table with admin actions to edit and delete. Then the form_remote_for at the bottom that sends an Ajax.Request

My teams_controller.rb create action:

def create
 @team = @league.teams.build(params[:team])
 if @team.save
  respond_to do |format|
   flash[:notice] = @team.name + ' was successfully created.'
   format.html { redirect_to teams_path(@team) }
   format.js {
    render :update do |page|
     page.insert_html :bottom, :teams, :partial => "partials/assets/team", :object => @team
     page.replace_html :notice, "<p>"+flash[:notice]+"</p>"
     page.show 'notice'
     page.visual_effect :highlight, 'notice'
    end
   }
  end
 else
  respond_to do |format|
   format.html { render :action => "new" }
   format.js {
    render :update do |page|
     page.visual_effect :shake, "team_name_para"
     page.replace_html :team_name_label, @team.errors.full_messages
     page << "$('team_name_para').addClassName('form_error_message');"
    end
   }
  end
 end
end

This is pretty basic as well, we have the usual if @team.save and the html format in the respond to. What you want to look at is the format.js block. Instead of rendering a rjs file, were just going to take care of everything right in the controller. The first page.insert_html inserts the content from the team partial that gets the @team object passed to it. Partial looks like this:

<tr>
 <td><%= link_to @team.name, team_path(@team.id) %></td>
 <% if logged_in? -%>
  <td>
   <%= link_to_remote image_tag('file_remove.png'), :url => team_path(@team.id), :method => :delete, :confirm => "Are you sure?" %>
   <%= link_to image_tag('file_edit.png'), edit_league_team_path(@league.id, @team.id) %>
  </td>
 <% end -%>
</tr>

So basically that just renders to the bottom of the table… Then the next 3 just handle the flash[:notice]. I put in some scriptaculous goodness as well. One issue I had was the flash[:notice]. In my application.html.erb layout I had:

<% if flash[:notice] -%>
 <div id="notice">
  <%= flash[:notice] %>
 </div>
<% end -%>

But this wasn’t going to work with the page.replace_html :notice because the div didn’t exist yet until the flash was created. So I switch things up and applied css to the paragraph tag instead of the div:

<div id="notice">                       
 <% if flash[:notice] -%>
  <p><%= flash[:notice] %></p>
 <% end -%>
</div>

Now for the fun part… err umm not so fun error handling. You’ll notice that the if @team.save has an else like usual. So we can do format.js like above. First if there were errors I would shake the entire paragraph tag that contains the label, input and button. This is some more scriptaculous goodness and really tells the user there’s something wrong. Next because we are only working with one input we can replace the html inside the label with @team.error.full_messages and add a class name so we can turn it red so they know there’s an error on that field.

That’s it!! Pretty simple stuff. Also if you have something more complex with multiple input and fields we can handle the errors a bit differently. First you can put an empty div on your page somewhere:

<div id="ajax_form_errors"></div>

Then in the else statement just add this into the format.js block:

page.replace_html :ajax_games_form_errors, :partial => "partials/assets/errors"

Then the errors.html.erb partial:

<div id="errorExplanation" class="errorExplanation">
 <h2><%= @game.errors.count %> errors prohibited this game from being saved</h2>
 <p>There were problems with the following fields:</p>
 <ul>
  <% @game.errors.each_full do |msg| -%>
   <li><%= msg %></li>
  <% end -%>
 </ul>
</div>

What were doing here is basically just the same thing ActiveRecord::Errors does with it default setup for error handling. Looping over the errors and printing them out in a list item.

That’s it that’s all. Lemme know if you have any problems and I’ll try and help you out the best I can.

Leave a Comment
post icon

Safari renders blank page with Ruby on Rails 2.3 >

If you have upgraded your Rails to version 2.3 you might notice Safari renders a blank page when you access your localhost to view your app. Apparently it’s because the newer versions of Rails don’t work well with older versions of Mongrel. The fix is simple:

sudo gem update mongrel
Leave a Comment
post icon

Prototype and Scriptaculous Drop Down Menu

I’ve made a cool drop down menu system using Prototype and Scriptaculous javascript libraries that utilizes some of the cool effects to create an animated menu system.

Anyway here is droplicious v.2.1 I won’t be putting up new versions here anymore. It will now be at github (see link below… right below)

Droplicious at github: http://github.com/darrenterhune/droplicious

Please comment any bugs or other questions on this post, or submit issues at github Thanks!

Leave a Comment
post icon

Installing ImageMagick on Mac OS X Leopard

I recently just got the 24inch iMac and had to undergo the massive task of porting over everything from my MacBookPro. This included installing all the needed custom installs of Ruby, Rails, ImageMagick, RMagick, MySQL and configuring everything to work properly. I had the most trouble with ImageMagick, although it wasn’t that hard It still took me a bit to do. Now I hate mac ports, well I don’t hate but I don’t like how it install stuff everywhere. I like being able to control what’s being installed in a tidy fashion. So this is what I did to get ImageMagick working:

(more…)

Leave a Comment
post icon

Advanced Rails Recipes – Keeping Forms Dry and Flexible – Plugin

I’ve updated the previous patch of ElevatedFormBuilder to a Ruby on Rails plugin. You can now install it as a plugin from my github:

script/plugin install git://github.com/darrenterhune/elevated_form_builder.git

If anyone has any problems just add comments below.

Formtastic is far superior than this plugin so you should check that out instead.

Leave a Comment