Rails 3 has adopted Unobtrusive Javascript and moved all the _remote functions to a plugin. They did this in an effort to remove all the inline spaghetti code produced by the helpers and provide a more modular way to deal with Javascript & Ajax. I must admit I like the convenience of the old helpers, but its not really the best way to do things if you are dealing with a complex app that uses alot of Javascript. So anyways, you will get the following error if you try to use the link_to_remote function: undefined method ‘link_to_remote’
In order to use UJS in your Rails 3 app, you need to do the following:
1. Use the new javascript file, rails.js along with your favorite javascript framework
In your layout, you can use the default javascript tag to include this and prototype:
The only problem with this method is that it may add javascript files that you don’t need and this adds to page load time. I like to take advantage of the Google hosted javascripts. Most people already have them cached and chances are Google will serve the files faster than your hosting company. I am using some of the scriptaculous libraries so I include that tag too. Here is what I use:
Make sure you put the rails js tag after prototype. I wasted 30 minutes figuring that out.
Rails 3 makes it easy to use jQuery or Mootools if you prefer them over Prototype. Just include them instead.
2. Use the forgery protection meta tags: <%= csrf_meta_tag %>
Rails uses these to prevent XSS attacks. I don’t know the details, so I will not go into it.. but you need to have this helper which spits out 2 meta tags:
Don’t hard code these. The helper provides a unique token.
3. Change your link_to_remotes to link_to and use the :remote parameter
Lets say you have a list of widgets and people can vote Yes or No as to whether they like the widget. After they vote, it updates the box with a highlight and changes the text to show you the vote result. Here is my big ugly Rails 2 version of this:
Here is what you do in Rails 3 (please ignore the ugly path.. we are renovating):
You now use a regular link_to tag and pass the :remote parameter as true.
4. Use a js.erb file instead of render :text=>”blah blah”
The link_to tag does not accept :update, :complete, etc., like the link_to_remote tag did. You can drop in a js.erb file to handle this stuff instead. I determine the text and color of the highlight in my controller action. /myapp/app/views/widgets/vote.js.erb
Rails sends this back to your page and the javascript is executed. This is a simplistic solution and the first one I found to produce the same behavior as my original Rails 2 helper. There may be better ways to do this, but for now this works for me. Here are some resources that I found useful when figuring this out:
Ryan Bates screencast was very helpful and most of this stuff was “inspired” from that. Props Ryan, good stuff as usual -> http://railscasts.com/episodes/205-unobtrusive-javascript
Simone Carletti has a good overview on UJS in Rails 3, and is more geared towards jQuery – http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-in-rails-3/
Another jQuery example – http://joshhuckabee.com/jquery-rails-3




#1 by Andrew Hadinyoto on October 16, 2010 - 9:21 am
Quote
Thanks a lot for this tutorial. It’s exactly what I was looking for.
#2 by Kevin on July 2, 2011 - 1:51 pm
Quote
Very, very helpful. I was especially happy to see how you handled :update, :complete, etc. I also had used :before which I converted to
nclick.
Thanks!
#3 by Edgar Silva on August 11, 2011 - 11:46 am
Quote
This works fine for GET requests, but if you have to make any POST request using :remote (like when creating, deleting or updating in a RESTfull implementation) the session is going to be blank because the authenticity token is not passed in this cases; the forgery protection in rails and prototype prevents this. For this to work when calling a :destroy (:method => :delete) or :update action with :remote set to true (an AJAX call) the authenticity token needs to be included manually in the parameters of the request like this:
“items”,
:action => ‘destroy’, :id => item,
:authenticity_token => form_authenticity_token },
:method => :delete, :remote => true %>
with this you can make sure in the controller action to handle requests properly, for any format (:js, :html,
ml)
regards, hope this helps.
#4 by Edgar Silva on August 11, 2011 - 11:48 am
Quote
Previous comment did not paste code correctly:
link_to ‘Delete’,
{ :controller=>”line_items”,
:action => ‘destroy’, :id => line_item,
:authenticity_token => form_authenticity_token },
:method => :delete, :remote => true