So I modified my Shovell code to use unobtrusive jQuery. It works.
Instead of using the form_remote_tag helper, I am using a regular form_for helper:
<div id="vote-form"> <% form_for [ @story, Vote.new ] do |f| %> <p><%= f.submit 'Shove This' %></p> <% end %> </div>
The following HTML is generated:
<div id="vote-form"> <form action="/stories/4-hell-breaks-loose/votes" class="new_vote" id="new_vote" method="post"> <div style="margin:0;padding:0"> <input name="authenticity_token" type="hidden" value="qA83IKqd05mqmSl8zyigMzmPeK+o6A+m7b683FhN16U=" /> </div> <p><input id="vote_submit" name="commit" type="submit" value="Shove This" /></p> </form> </div>
Not a trace of JavaScript in it.
Both the jQuery library and application.js are included on the page, so I open application.js and add this JavaScript:
// Place your application-specific JavaScript functions and classes here // This file is automatically included by javascript_include_tag :defaults jQuery(function() { jQuery('#new_vote').submit(function() { // $.post(url, data, callback, type) jQuery.post( jQuery(this).attr('action'), jQuery(this).serialize(), null, 'script' ); return false; }); });
Ryan Bates' code would have been — if I am to look at the source code provided with his jQuery screencast:
// Place your application-specific JavaScript functions and classes here // This file is automatically included by javascript_include_tag :defaults jQuery.ajaxSetup({ 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")} }) jQuery.fn.submitWithAjax = function() { this.submit(function() { $.post(this.action, $(this).serialize(), null, "script"); return false; }) return this; }; $(document).ready(function() { $("#new_review").submitWithAjax(); })
I don't need to set my request header to accept “text/javascript”. I ran my app in Safari, IE6, IE7, IE8 and Firefox, and it worked just fine there. Ryan Bates was using jQuery v1.2.6 when he recorded his screencast on Nov 17, 2008 — I'm using jQuery v1.3.2. Maybe that explains it?
I create a create.js.erb template in app/views/votes and in it I place a simple alert with embedded Ruby in it. See what I get:
Of course, my votes controller has been set to be able to respond to both a regular POST request and a remote Ajax one:
class VotesController < ApplicationController def create @story = Story.find(params[:story_id]) @story.votes.create flash[:notice] = 'Thanks.' # The following would work too. # unless request.xml_http_request? # redirect_to @story # end # Rails uses the HTTP Accept header to determine the request type. respond_to do |format| format.html { redirect_to @story } format.js end end end
It was easier than I thought. It took me 3 minutes to figure things out. This demo page on the jQuery UI website was useful.
So, to accomplish exactly the same thing that was previously done by my create.js.rjs template:
# replace the content of #id with this HTML page.replace_html 'vote-score', "Score: #{@story.votes.count}" # apply visual effect :effet_type to the content of #id page.visual_effect :highlight, 'vote-score', :duration => 2
I am now using these chained commands on my #vote-score div in create.js.erb:
jQuery('#vote-score').html("Score: <%= @story.votes.count %>").show('highlight', {}, 2000);
I am writing my own JavaScript, jRails is not writing it for me, but it's jQuery so it's mindnumbingly easy.
The JavaScript that was sent to the browser when using jRails was pretty much the same — except it was wrapped in a Try and Catch construct:
I am so dumb: I should have referred to it when figuring out how to code my effect.
The JavaScript now returned — the one I had to write, that was not generated by Rails — is this one:
If I feel lazy, I guess I can use RJS.
Of course, one can make his jQuery unobtrusive and still use RJS templates. As long as you don't use form_remote_for, form_remote_tag, link_to_remote and periodically_call_remote helpers, but add event handlers to application.js instead, then you're good.
Comments
Why start with rails?
Ruby on Rails is awesome and all, but I was a little overwhelmed when I started. I then moved on to just Ruby and converted my Drupal site to Octopress. I may go back to Drupal but only if I want to actually build an application with it rather than just a website.