jQuery and Rails 3: A mini tutorial
As most of Rails developers, recently I’ve been through a process of unlearning all concepts of older versions of Rails and learning again the new ones of 3. But hey! I must admit that so far it’s been more pleasure than pain as things only get simpler and more natural than they used to be!
Here I’d like to talk about how simple it has become to integrate unobtrusive jQuery to a Rails app. Let’s use as an example a system of comments. I’ll create a simple app to create YouTube like comments:

Start typing in your teminal:
rails myCommentsApp
rails g resource Comment name:string body:text
rake db:migrate
Then we have to include the jQuery library and the jQuery driver file and place it inside /public/javascripts/ (or grab the helpers generator of Code Officer and do it automatically if you wish). Now remove the javascript_include_tag :defaults in the layout and add the following includes:
/app/views/layouts/application.html.erb
javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"
javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"
javascript_include_tag "jquery-rails.js"
Now let’s add some logic to our program. We’ll start out with an index action that will get all the comments:
/app/controllers/comments_controller.rb
def index
@comments = Comment.all
respond_to do |format|
format.html # index.html.erb
format.rss
end
end
And the views for the index will look like this:
/app/views/comments/index.html.erb
<span id="comments_count"><%= pluralize(@comments.count, "Comment") %></span>
<div id="comments">
<%= render :partial => @comments, :locals => { :list => true } %>
</div>
<hr />
<div id="comment-notice"></div>
<h2>Say something!</h2>
<% form_for Comment.new, :remote => true do |f| %>
<%= f.label :name, "Your name" %><br />
<%= f.text_field :name %><br />
<%= f.label :body, "Comment" %><br />
<%= f.text_area :body, :rows => 8 %><br />
<%= f.submit "Add comment" %>
<% end %>
Notice that the new attribute remote is all we need to worry about when creating a form that will submit with Ajax. Rails 3 works with HTML5 attributes, so it only adds the attribute data-remote=”true” to the form and that’s it, the jQuery driver will handle the rest.
We’ll create a partial for the comments:
/app/views/comments/_comment.html.erb
<%= div_for comment do %>
<span class="dateandoptions">
Posted <%=time_ago_in_words(comment.created_at)%> ago<br />
<%= link_to 'Delete', comment_path(comment), :method => :delete, :class => "delete", :remote => true %>
</span>
<p><b><%= comment.name %></b> wrote:</p>
<br />
<%= content_tag(:p, comment.body, :class => "comment-body") %>
<% end %>
So now let’s add the fireworks! That is, the asynchronous creation and deletion of comments along with some trendy effects. We come back to the CommentsController and add the actions:
/app/controllers/comments_controller.rb
def create
@comment = Comment.create!(params[:comment])
flash[:notice] = "Thanks for commenting!"
respond_to do |format|
format.html { redirect_to comments_path }
format.js
end
end
def destroy
@comment = Comment.find(params[:id])
@comment.destroy
respond_to do |format|
format.html { redirect_to comments_path }
format.js
end
end
And we are done with the logic part! A few javascript lines will end the work:
/app/views/comments/create.js.erb
/* Insert a notice between the last comment and the comment form */
$("#comment-notice").html('<div class="flash notice"><%= escape_javascript(flash.delete(:notice)) %></div>');
/* Replace the count of comments */
$("#comments_count").html("<%= pluralize(Comment.count, 'Comment') %>");
/* Add the new comment to the bottom of the comments list */
$("#comments").append("<%= escape_javascript(render(@comment)) %>");
/* Highlight the new comment */
$("#comment_<%= @comment.id %>").effect("highlight", {}, 3000);
/* Reset the comment form */
$("#new_comment")[0].reset();
/app/views/comments/destroy.js.erb
/* Eliminate the comment by fading it out */
$('#comment_<%= @comment.id %>').fadeOut();
/* Replace the count of comments */
$("#comments_count").html("<%= pluralize(Comment.count, 'Comentari') %>");
Finish! That’s all the effort you need nowadays to a create a Web 2.0 fashionable feature such as this one. Of course, you need some styling with CSS, and you would need tons of more things in the real world (such as antispam, authentication, something to comment about…) but that’s the part I chose to talk about today!
I pushed myCommentsApp to Github in case you want to have a closer look (or download the zip version).
You might be interested in checking out my script for letting user in-place edit your application contents.
Tags: ajaxcommentsjqueryrails 3tutorial
60 Comments »






60 Comments on “jQuery and Rails 3: A mini tutorial”
Follow comments feed
Wow that code looks familiar to me!
That’s a very useful code, I think every comment system should be like this by now, people is getting used to it and feels weird the get the old school redirect.
Also, this code is perfectly compatible with Rails 2, except in rails 2 you don’t need the “jquery rails driver” but the jrails plugin, and instead of using form_for with the :remote => true you should use remote_form_for.
PS: The textarea for submitting comments (in your blog, no the example app) has way too big font size! I have like 4 words per line XD
PS2: I like the new imperative to attract people to comment…
Of course it is familiar to you dude, I coded it first for our joint project semantic.cat (http://github.com/bernat/semantic) and copy&pasted after to my blog, so as to be useful to someone else (which may not be the case).
Indeed, the way you code Ajax actions now and before hasn’t changed that much apparently, though it has in the inside. Taking profit of HTML5 attributes now there’s no need to add blocks of javascript code mixed with markup, you redefine everything separately in your “driver”. In fact, you can capture more actions defining new remote handlers almost painlessly, creating as “data-” attributes as you wish.
You’re right about the font-size being too big, I’ll have it change… someday!
[...] equivalent for Prototype helper plugin yet so that would be an issue like in my case. Based on this jQuery and Rails 3 tutorial, using the jQuery UJS driver looks very [...]
Thanks, it has been really useful for me.
Wow, thanks ! This tutorial was exactly what I was looking for. Now I think I even understand the use of .js.erb files !
tes
Hi dude! That’s great
Cheers for the tutorial… helped me get a few cool things working :)
Thanks alot! This was very handy, thanks for putting it up!
Thanks for the tutorial. It was exactly what I needed. Even better, your code on github worked with zero trouble.
[...] equivalent for Prototype helper plugin yet so that would be an issue like in my case. Based on this jQuery and Rails 3 tutorial, using the jQuery UJS driver looks very [...]
Thanks for the article, very useful…
I found an issue with this method of using jquery – escape_javascript removes javascript from the partial. What happens if you need javascript in the partial? for example for autocomplete?
Thanks for sharing this quick tutorial… its very helpful.
Regards
Puneet
Hey Moshe, excuse me I did not see your reply. This was just the simplest of all possible ways to do it but of course you don’t have to escape javascript, once you’ve got the @comment you can display it the way you like and use all the power of jQuery. If you give me a specific example I can try to help.
Hi thanks for the guide, helped me a lot. One thing I don’t understand is how the flash message is shown
“flash.delete(:notice)” this part especially seems strange because of the delete word when we’re trying to show it.
Hello Sunny,
when you display a flash notice you want to do both things at a time: One is to actually display it and the other is to clear it out so it won’t show up at the next request. With flash.delete[:notice] we do both.
nice, thanks.
Hi, thanks for that very nice tutorial :) But I have a
problem ;) I have exectly the same code and it works all fine
expect of the all the things in the create.js.erb :-/ There is no
highlighting or notice… I use Mozilla Firefox 3.6.11 I got the
following failure in the failure console of firefox: Fehler:
uncaught exception: [Exception... "Cannot modify properties of a
WrappedNative" nsresult: "0x80570034
(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN)" location: "JS frame ::
chrome://global/content/bindings/autocomplete.xml ::
onxblpopuphiding :: line 825" data: no] Is there any other way to
get your nice result without that exception?
yaaaayyy! awesome
This is great, awesome, woo yeah!
something!!!
uahuuuuu !!!
awesome
Nice tutorial. Some improvements are needed nevertheless:
- add validations for a comment(no empty comment body or comment name)
- flash notice need to be fade out after deleting a comment, for example like that:
$(‘.flash.notice’).fadeOut(); #in destroy.js.erb
Great stuff!
Fantastic tutorial! It’s been really useful :)
Hi,
i have some prblems. all code works fine, but, if i have a “format.html” on respod_to and in template a button_to with :remote => true, the format.js dont respond, always shows the format.html unless i comment that line.
how can i fix that? maybe i doing something wrong.
thanks.
I’m not sure I understand your problem. If you add a :remote => true in your template AND you have the jQuery driver for Rails Helpers added in your layout, you should be able to catch a JS request by adding the format.js line in the respond_to block. If it goes to format.html, as you say, it’s because you are doing a regular synchronous request. Probably not have the jquery.rails.js. If you do a JS (AJAX) request you will only notice what happens by looking at your server console.
THanx, man.. good mini-tutorial! :)
good one
Thank you. Very informative.
> As most of Rails developers, recently I’ve been through a
> process of unlearning all concepts of older versions of Rails
> and learning again the new ones of 3.
Is there a good starting point to learn the concepts? I tried to find something, but not sure yet.
I have also tried to run your application. But it doesn’t work. Once I have submitted the form it stops with an error message. However, the record is stored in the database. Do I have to install or copy any js libaries before running the application?
I just tried again with the zip-file. After extracting, I did:
bundle install
rake db:migrate
rails s
In the browser I add a comment and pressed the submit button. Nothing happened in the browser and in the console I got the following error message.
http://bit.ly/dYHJg7
Any ideas?
Wow this is very nice!
This is nice tutorial. Facing problem in one case. After AJAX request, I want to redirect_to different page instead of updating RESPONSE in any div, how can we do this ?
Hi,
it seems your
$(“#new_comment”)[0].reset();
doesn’t reset the comment form, nor does
$(“#new_comment”).get(0).reset();
seem to help :/
The rest seems to work.
Thanks for writing this blog entry, everything worked great. I’m unclear about the following statement:
render :partial => @comments, :locals => { :list => true }
I cannot seem to find out where the locals :list is being referenced. Where should I be looking? I poked around the ‘render’ documentation and also div_for and contact_tag_for and was unable to understand how that symbol is being used.
Thanks again!
Nice!
Hi paul,
As I understand, rails will look for a file called _comments under your comments folder in your views, and in this file (_comments.html.erb) you should be able to access the comment variable as a list.
So, this way, you don’t have to do an “for” to generate it.
Hope it helps anyway.
Thanks for the nice tutorial
Thanks for this tutorial….It helped me a lot in developing my own rails app :)
This is awesome tutorial!
Fantastic. Very well done — I searched high and low for something as clear and straightforward as this. I was able to quickly move forward on a project I’ve been working on, and had hit a roadblock. Thank you!
I like it your post because i implemented that on my project but i try to add email for gravatar photo will appear in the comment .. it says error how to do it..
Thanks in advances
Well done! but why did you not put -J in the first rails calls, that would spare you deleting files ;-)
Hi, love the tutorial and the commenting system is very nice.
I love you man thanks a bunch from a junior rails developer :)
Man there is an error:
Missing template comments/create with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths “/home/carlo/Desktop/myCommentApp/app/views”
Hi, I like your tutorial. Short and sweet. I have a question. I am trying to create a http link that will invoke a form submit via ajax. How can I do it?
Nicely done sir!
This was a great help — thanks. BTW, a slightly cleaner way to include jQuery in your app:
[1] add the line
gem 'jquery-rails'to your Gemfile[2] execute
bundle installon the command line[3] execute
rails generate jquery:installon the command lineThat will remove the unused prototype code, install jQuery and jquery_ujs. Now you can leave the original
javascript_include_tag :defaultsin views/layouts/application.html.erb.@bernat: I liked your example so much that I made a fork of myCommentsApp and tweaked it to use the latest Rails with postgresql with README instructions on how to deploy it on Heroku. See github link above.
thanks a lot.
I really appreciate the simplicity of the tutorial. I still have not yet digested all of it, but it’s in a wonderful bite sized chunk. Thanks!
Nice tutorial.
Thanks a lot :)
~gurufrequent
Thanks a lot, Bernat – this was very helpful for me too… nice job writing: just enough info but not more.
Thanks for the tutorial.
I’m really new to Ruby on Rails, but I was curious. How could the Web page “invoke” the functionality of a form submission, in order to activate Javascript/JQuery code?
Perhaps this is a fundamental axiom with this framework, but I’m very green to RoR.
I currently have Ruby 1.8.7 and Rails 3.0.9. I’ve also installed the “jquery-rails” gem, whereby my application uses JQuery for its Javascript library, rather than Prototype. How would I update information, dynamically, “after” a page loads?
I’m trying to fetch info from another site for an area of a page, after it’s loaded. I don’t want the user to wait for the entire page to load, because the page is waiting for one DIV’s content to render.
Would anyone have any feedback on that? I’ve thought of doing the work you outline in this tutorial, but I don’t want to have to force a user to click on a form link on my page, in order to do that.
Any feedback would be GREATLY appreciated. Thanks in advance RoR community!!
Thank you so much for the tutorial.
i liked it very much.
Thank you for sharing.
this is the best lesson of ajax thanks a lot