Friday, March 21, 2008

Tutorial: Beginning AJAX with Rails 2.0

Today, I'm going to go over a quick tutorial of some basic AJAX functions. Rails has a great implementation with AJAX right out of the box, with the Prototype library. It also includes the Scriptaculous library with some special effects. We are just going to do some basic writing text into the site without page reloading. Lets get started.


Set up the application:


 
rails ajaxtest -d mysql
cd ajaxtest
./script/generate model Foobar foo:string bar:string
./script/generate Controller Foobars

This is our first project that doesn't use scaffolding - I decided against it because scaffolding would have generated all kinds of views we aren't going to need for this. Notice that when you created the model, it automatically generated your DB migration file. Now, lets open up app/controllers/foobars_controller.rb and do this:



class FoobarsController < ApplicationController
def index
@foobars = Foobar.find(:all)

respond_to do |format|
format.html # index.html.erb
end
end

end

Next, create app/views/foobars/index.html.erb:



<h3>Foobars!</h3>
<table>
<tr><th>Foo</th><th>Bar</th></tr>
<% for foobar in @foobars do %>
<tr>
<td><%= foobar.foo %></td>
<td><%= foobar.bar %></td>
</tr>
<% end %>
</table>

Now lets add our routing. In config/routes.rb add:


  map.resources :foobars

In your console, lets get our db created and foobars table setup:



rake db:create
rake db:migrate

And one last thing. We need to populate our table with a few foobars. This is a good time to show you the rails interactive console:


./script/console

From here, we can give commands directly to our project. Lets try one:


Foobar.find(:all)


>> Foobar.find(:all)
=> []

So it returned an empty array. The interactive console is great for playing around with bits of code to see what they do or even testing out bits of code. Lets try another command:



>> myfoobar = Foobar.new
=> #<Foobar id: nil, foo: nil, bar: nil, created_at: nil, updated_at: nil>
>>

Creates a new foobar object...



>> myfoobar.foo = "This is a test."
=> "This is a test."
>> myfoobar.bar = "This is only a test."
=> "This is only a test."
>>

We can set the values of foo and bar for our new foobar, and...



>> myfoobar.save
=> true
>>

We can save it to the database. Lets try looking it up with find...



>> Foobar.find(:all)
=> [#<Foobar id: 1, foo: "This is a test.", bar: "This is only a test.", created_at: "2008-03-21 18:24:46", updated_at: "2008-03-21 18:24:46">]
>>

Great - so far so good. Now lets create a few more foobars:



myfoobar = Foobar.new
myfoobar.foo = "Foo of foobar #2"
myfoobar.bar = "Bar of foobar #2"
myfoobar.save

myfoobar = Foobar.new
myfoobar.foo = "Foo of foobar #3"
myfoobar.bar = "Bar of foobar #3"
myfoobar.save

myfoobar = Foobar.new
myfoobar.foo = "Foo of foobar #4"
myfoobar.bar = "Bar of foobar #4"
myfoobar.save

And done. You can type exit to leave the interactive console. Start the server, browse to localhost:PORT/foobars



Tablespoon of AJAX


First thing, I'm going to tell you that if you don't have Firebug yet, go ahead and get it. It is a plugin for Firefox(you are using firefox, right? nothing against you Safari/Opera lovers..if you are using IE you have no excuses, get Firefox and get Firebug...now). Firebug is a great tool for design as well as for AJAX. The inspect mode will highlight divs under your mouse and show the corresponding html/css code in the panel below. You can also take a look at Javascript AJAX responses and more quickly debug your code. Lets create app/views/layouts/application.html.erb:



<html>
<head>
<%= javascript_include_tag :defaults %>
</head>
<body>
<%= yield :layout %>
</body>
</html>

The include tag will include (among other things) the prototype library that you need to make the AJAX calls. Now, lets head back to app/views/foobars/index.html.erb and set it up for our AJAX. Change it to this:



<h3>Foobars!</h3>
<table>
<tr>
<th>Foo</th>
<th>Bar</th>
<th>Which?</th>
<th>Links</th>
</tr>
<% for foobar in @foobars do %>
<% idstring = "foobar-" + foobar.id.to_s %>
<tr>
<td><%= foobar.foo %></td>
<td><%= foobar.bar %></td>
<td id="<%= idstring %>"></td>
<td>
<%= link_to_remote "Foo", :url =>{ :action => :set, :updatewith => foobar.foo },
:update => idstring %>
  
<%= link_to_remote "Bar", :url =>{ :action => :set, :updatewith => foobar.bar },
:update => idstring %>
</td>
</tr>
<% end %>
</table>

We have 2 more columns in our table now - Which? will be updated by AJAX with either the foo or the bar of our current Foobar depending on the link clicked from the Links column. In the Links column, we have 2 link_to_remote 's. link_to_remote generates all the javascript calls to send an AJAX request back to our controller on the server. The first argument is what will be displayed for the link. In :url, we define the action to send the request to (:set), as well as the string we want to pass into the function (:updatewith). Last, :update will be the name of the div we will be updating. You can also add another parameter, :position. For example, :position => :before would insert whatever you are sending before the td tag, :after would be after it, :top would insert it inside the td, above anything else, and :bottom inserts it inside the td, at the bottom. If you do not specify a position(like we are doing), it will simply over-write what is inside the div. One more thing to do; lets open up app/controllers/foobars_controller.rb and add in our :set action:



def set
render :text => params[:updatewith]
end

Go back to the page and try clicking the links



Update: I found this link to be very helpful with different ways of using render with AJAX.



And we are done! Thanks for visiting, and see you next time.



16 comments:

runpin said...

OH MY, you are hero!!!

Anonymous said...

Thanks a lot for this great introduction to Ajax.

Unknown said...
This comment has been removed by the author.
Unknown said...

Informative post, thanks. A heads up, the equivalent of firefox's firebug for Safari is webkit, http://webkit.org/.

Unknown said...

Short and sweet.
Both your tutorial and the Ruby-Ajax integration it demonstrates.

I'd like to add my applause.

Unknown said...

Really nice tutorial for beginners like me :)... Can you also tell us how to dynamically bring data while the user is typing a text (like suggestions in google search) ?

rledge21 said...

@Pratik Rails has AJAX helpers for this, the observe_field function would be of interest for you with this.

http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper.html

Dans said...
This comment has been removed by the author.
David said...

If i wanted to save the text being displayed under 'Which?' how would i go about doing that. In other words, i'm wondering how i would go about databasing the value that is being displayed there. Thanks for a great blog!

Bryan said...

Just started learning Ajax and it's difficult to find simple examples on the net.

Thanks you for this one !

Was hoping you could post more ?

Unknown said...

Thank you very much for your time, it helps me a lot.

Roberto Leite said...

That's awesome! Easy to understand, quick to reproduce. Thank you very much for this tutorial.

Anonymous said...

In order to get this 100% working, add this in routes.rb instead of the one in the article:

map.resources :foobars, :collection => {:set => :post}

adslfk said...

Short and easy

BragBoy said...

What a sweet and cute little independent tutorial focussing only on the AJAX of Rails!!!!!

Great Job1

sildenafil citrate said...

This code didn't work on my PC, please repost the formulas, I'm near to become mad about this stuff.