Rails, Prototype, and JQuery in Harmony (or how to replace Prototype with JQuery)

08 April 2010

It has become common practice to use JQuery as the javascript library of choice for Ruby on Rails applications. If you have a Rails app already using Prototype, it usually isn't feasible to replace it in one swoop. And sometimes, you just simply need both to work at the same time. Whether you want to use both in unison (not recommended as a long-term strategy), or you want to gradually migrate from Prototype to JQuery, it's not as scary as you may think.

The secret is that it is difficult to get Prototype to play nicely with JQuery, while it is rather trivial to get JQuery to play nicely with Prototype. This may seem like a minor distinction, but it is one that will save you a lot of headaches.

Use Prototype/Scriptaculous with JQuery

First, in our application layout, we're going to get rid of `<%=javascript_include_tag :defaults %>` and include each javascript file explicitly just to make things a little less magicky and a little more straight forward.

<%= javascript_include_tag 'prototype', 'scriptaculous', 'application' %>

Now, we'll add in JQuery (and JQuery UI while we're at it, just for fun). You'll want to grab the latest release from the JQuery download page (and the latest JQuery UI as well).

<%= javascript_include_tag 'prototype', 'scriptaculous', 'jquery', 'jquery-ui', 'application' %>

Right under that line, in your Rails application layout, we'll insert the one-liner that makes JQuery play nicely with Prototype, YUI, etc.

<script>
  // this allows jquery to be called along with scriptaculous and YUI without any conflicts
  // the only difference is all jquery functions should be called with $j instead of $
  // e.g. $j('#div_id').stuff instead of $('#div_id').stuff
  var $j = jQuery.noConflict();
</script>

Try doing this with Prototype (especially if you're using other scripts built on top of Prototype and Scriptaculous), and you'll soon find yourself pulling out your hair.

If you simply want the ability to use both libraries together in your app, then congratulations, you're done. You can now do this:

Effect.Fade($('element_id'));
$j('#element_id').show();

Notice the first line uses the Prototype element id selector, $ with a Scriptaculous effect, and the second line uses the new noConflict JQuery selector $j.

Make Rails Use JQuery Instead of Prototype

Update: This is actually even easier now with Rails 3. All you have to do is tell Rails to use the jQuery API javascript file instead of the Prototype API javascript file. See this Rails3-jQuery project on Github for using jQuery natively with a Rails 3 application.

Let's assume that we'd like to phase Prototype out of our app in favor of JQuery. In addition to going through your application and replacing all of your Prototype code with JQuery code, you'll need to take care of the Rails Prototype helper magic (note that when Rails 3 becomes the standard, this won't be necessary).

This is really easy, thanks to the JRails plugin, which can be found on Github. Install it in your Rails project from your root directory.

.script/plugin install git://github.com/aaronchi/jrails.git

Now, your Rails helpers, such as link_to_remote, form_remote_tag, etc. are using JQuery to build the AJAX code instead of Prototype on the back end. Isn't Rails magic neat?

Caveat: Delayed Observer

Update: If you are trying to get delayed observer to work with jQuery in a Rails 3 application, see my comment below.

There is one more step if you're using the observe_form helper method. This helper relies on Prototype's Element.observe method, which does not exist in the standard JQuery library.

No worries, someone has done the work for you already (not me). Just download and include the JQuery delayed observer plugin in your layout, and you're all set.

<%= javascript_include_tag 'prototype', 'scriptaculous', 'jquery', 'jquery-ui', 'jquery.delayed-observer', 'application' %>

Boot Prototype Once and For All

Once you've eliminated all Prototype/Scriptaculous code from your project (meaning there should now be no $ references in your entire project, only $j), you can simply remove it Prototype0+Scriptaculous from your project.

<%= javascript_include_tag 'jquery', 'jquery-ui', 'jquery.delayed-observer', 'application' %>

And just to celebrate, remove the var $j = jQuery.noConflict(); line from your application layout, and do a Find and Replace All $j with $ for your project. You have now ditched Prototype once and for all.

About the author:

Steve Schwartz // Owner of Alfa Jango, CTO of Genomenon, co-founder of Carcode (acquired by Edmunds.com in 2014), engineer, developer, open-source enthusiast, guitarist, and racecar driverist.



Comments are loading...