33

I have this setup:

class UsersController < InheritedResources::Base
  respond_to :html, :js, :xml, :json

  def index
    @users = User.all
    respond_with(@users)
  end
end

Now I am trying to make it so, if params[:format] =~ /(js|json)/, render :layout => false, :text => @users.to_json. How do I do that with respond_with or respond_to and inherited_resources?

Lance
  • 75,200
  • 93
  • 289
  • 503

7 Answers7

46

Something like:

def index
  @users = User.all
  respond_with @users do |format|
    format.json { render :layout => false, :text => @users.to_json }
  end
end
Yannis
  • 5,426
  • 1
  • 31
  • 30
28

Assuming you need JSON for an Ajax request

class UsersController < InheritedResources::Base
  respond_to :html, :js, :xml, :json

  def index
    @users = User.all
    respond_with(@users, :layout => !request.xhr? )
  end
end

This seems like the cleanest solution to me.

Anthony Bishopric
  • 1,306
  • 11
  • 23
18

Or to prevent you having to hardcode responses for each format in each action.

If you have no layouts for any of the actions in this controller it would be nicer to do:

class UsersController < InheritedResources::Base
  respond_to :html, :js, :xml, :json
  layout false

  def index
    @users = User.all
    respond_with(@users)
  end
end
Jeremy
  • 4,880
  • 1
  • 19
  • 15
  • In rails 3 use layout: false - nil will load the default layout. See: http://stackoverflow.com/a/11355276/398696 – d3vkit Feb 26 '13 at 01:41
8

I love @anthony's solution, but didn't work for me... I had to do:

respond_with(@users) do |format|
  format.html { render :layout => !request.xhr? }
end

ps: posting an "answer" instead of a comment because stackoverflow comment formatting and "return key == submit" is infuriating!

choonkeat
  • 5,557
  • 2
  • 26
  • 19
5

I just found this out:

Even if it's JSON, Rails is still looking for a layout. As such, the only layout that it finds, in our case, is application.html.

Solution: Make a JSON layout.

So for instance, if you put an empty application.json.erb with a single = yield inside, next to your HTML one, the HTML layout is bettered by the JSON one. You can even use this to surround your JSON with metadata or things like that.

<%# app/views/layouts/application.json.erb %>

<%= yield %>

No other parameters needed, it automagically works!

Tested in Rails 4 only

Jonathan Allard
  • 18,429
  • 11
  • 54
  • 75
  • Tested in Rails 3, works just fine. While it isn't an answer for the question asked, it is still the answer for the question a lot of us mean for real. – lifecoder Mar 30 '14 at 19:49
  • Works for me in Rails 4. Simple and straightforward. – Petercopter Sep 22 '14 at 04:43
  • 2
    I've just checked in Rails 4.2. If you name your layout file `application.html.slim`, it wouldn't be treated as layout file for json; whoever, if you name your layout file as `application.slim`.. then it *would* be treated as layout file for JSON. (replace slim with erb should do the same thing). – songyy Jan 23 '16 at 17:52
2
class UsersController < InheritedResources::Base
  layout -> (controller) { controller.request.xhr? ? false : 'application' }
end
Moriarty
  • 3,957
  • 1
  • 31
  • 27
1

You need to set this on your show action.

def show
  render :layout => !request.xhr?
end

:)

rafudu
  • 43
  • 1
  • 6