3

I'm running the latest Rails 2-3-stable branch (currently 2.3.3).

I'm using JQuery to post an AJAX request to my 'create' action, in which I have the following block:

respond_to do |format|
  format.js
end

I have created create.js.erb and to test this action, I've added the following single line:

alert('hello');

The request correctly enters the format.js block, but the response attempts to render a layout. Here's my log:

Jul 22 20:44:27 [2970] INFO: Rendering template within layouts/application
Jul 22 20:44:27 [2970] INFO: Rendering contacts/create

If I change my respond_to block to the following, it works:

respond_to do |format|
  format.js { render :layout => false }
end

Is this expected behaviour or is this a bug in Rails? I would have thought the fact that I'm rendering a JS response would be enough to set layout to false.

sth
  • 222,467
  • 53
  • 283
  • 367
Olly
  • 7,732
  • 10
  • 54
  • 63

4 Answers4

10

I use this:

class ApplicationController < ActionController::Base
  # this is needed to prevent XHR request form using layouts
  before_filter proc { |controller| (controller.action_has_layout = false) if controller.request.xhr? }

It works like charm. You have to put this onliner only in one place and noting more.

I have spend ~1 h to write this line.

Szymon Jeż
  • 8,273
  • 4
  • 42
  • 60
2

The best way I've found to handle this is to add a file like this:

app/views/layouts/application.js.erb

<%= yield -%>

If you don't include the yield, your js actions will all fail, since the app will never render the view. This technique solves the layout problem and also offers the ability to add universal js code at the layout level, such as flash processing or triggering jQuery UI onLoad hooks.

Aubrey Goodman
  • 256
  • 2
  • 6
1

My memory of Ajax on Rails books is that this was the standard if not necessarily expected behaviour in earlier editions of rails.

The following ticket shows the bug logged a few versions back, as well as a way to define the behaviour as default.

http://dev.rubyonrails.org/ticket/3229

Sadly the description of what the later changes are that make this obsolete are not explained in the final comment.

Greg
  • 2,549
  • 2
  • 24
  • 30
0

The JQuery function which makes the Ajax POST request should return "false". Check if you are doing the same. It should be implemented like following:

postFormData: function () {
  $('#form_id').submit(function () {
    $.post($(this).attr('action'), $(this).serialize(), null, 'script');
    return false;
  });
}

Notice the last line which returns false.

Waseem
  • 8,232
  • 9
  • 43
  • 54