views:

307

answers:

3

I have an app running Rails 2.3.5 that has a JSON API for much of it.

A contractor came in and did some work on the app and used RJS in a few places. Some of those controller actions that are using RJS for the main web site also need to be part of the API.

The problem is that JSON API requests trigger the RJS responses, which is not what I want. I'd like the RJS responses to happen from a browser, but when it's an API request (as distinguished by using the "application/json" Accept and Content-Type headers) then I'd like it to just send the API response.

From what I can tell, Rails triggers an RJS response for any MIME Type that involves javascript, i.e.

text/javascript application/json

etc.

Is there a way to force RJS to only respond to text/javascript? Or is there a better way to solve this problem?

To make it more clear, I have code that looks like this:

def show
  @dashboard = @user.dashboard
  respond_to do |wants|
    wants.html
    wants.json { render :json => @dashboard }
  end
end

The trouble is, there is also a show.rjs template in the view folder for this controller. When someone hits the API, I want it to render the json results, as I have listed above, but instead, it renders the show.rjs template.

How can I make sure that API clients get the json results I want, and still let the RJS template render for people on the website?

A: 

In your controller's action try the following:

def index
  respond_to do |format|
    format.html # Renders index.html.erb as usual
    format.xml  { render :json => {:name => "raskchanky"}.to_json }
  end
end

According to Rails documentation (http://api.rubyonrails.org/classes/ActionController/Base.html) "render :json" sets the content type of the response to application/json.

Alex Kaushovik
+1  A: 

You will need json defined in your mime_types.rb and then you should be able to do this:

def show 
  @dashboard = @user.dashboard
  respond_to do |format|
    format.html
    format.json {render :json => @dashboard}
    format.js
  end
end

More to read here: http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/

Apie
A: 

Are you sure that your javascript is sending the correct headers? When I do rjs, generally I do this by responding to format.js. This allows my to easily separate json and js responses.

Generally, my problems have been in ensuring that my ajax actions are actually sending requests in the proper format. When in doubt, you can add a 'format':'js' parameter to your request. In jQuery:

// try to get it to figure out rjs actions by itself
$('a').click(function(e){
  e.preventDefault();
  $.get({
    url: this.attr('href'),
    dataType: 'script',
    success: responseFunction
  });
});

// or force the format
$('a').click(function(e){
  e.preventDefault();
  $.get({
    url: this.attr('href'),
    data: {format: 'js'},
    success: responseFunction
  });
});
Eric Saxby