Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails: How do detect if access by JSON?

I got a GET URL that calls a controller method getInfo. It can be called by mydomain.com/getInfo.json?params=BLAHBLAH or mydomain.com/getInfo?params=BLAHBLAH

In the controller, is there a way to detect how the user called it?

like image 311
Henley Avatar asked Sep 28 '11 02:09

Henley


4 Answers

Yes. Within the controller you can call the request.format method to determine the format requested by the user.

If you need more than just the format, you can look at request.url for the full URL. More details about the request object can be found here.

like image 80
Rob Sobers Avatar answered Nov 13 '22 19:11

Rob Sobers


Within your controller's specific method, you can respond to different formats - for example:

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

You can respond to various formats (xml, js, json, etc) - you can get more information about respond_to and how to use it in your controller here:

http://apidock.com/rails/ActionController/MimeResponds/InstanceMethods/respond_to

like image 42
michaeldcruz Avatar answered Nov 13 '22 19:11

michaeldcruz


Here is an actual somewhat contrived working example, that answers the question of how to detect if the call is JSON / XML API call vs an "HTML" call. (Accepted answer doesn't answer that question, just tells you how to respond to various formats)

# We can use this in a before_filter
skip_before_action :verify_authenticity_token, if: :api_request?

# Or in the action
def show
  @user = if api_request?
            User.where(api_token: params[:token]).first
          else
            User.find(params[:id])
          end
  respond_to do |format|
    format.html 
    format.json { render :json => @user }
  end
end

private
  def api_request?
    request.format.json? || request.format.xml?
  end

Using a respond_to sets different types of responses, but it doesn't tell your application how the call was made unless you add some extra code that does it (see below for a crude example, just to illustrate the point.)

I wouldn't recommend this, interrogating request is much safer, and 10x times more useful, as the approach below is only useful much later in the request lifecycle ( right before the response is sent back to the client). If you have any logic in your before filters this wouldn't work at all.

# Have no way of using it in a before_filter
# In your controller
def show
  # I want to know if the call was JSON API - right here 
  # This approach wouldn't help at all. 
  @user = User.find(params[:id])
  respond_to do |format|
    format.html { @api_request = false}
    format.json { @api_request = true; render :json => @user }
  end
end

def api_request?
  @api_request
end
like image 12
konung Avatar answered Nov 13 '22 21:11

konung


A list of ways to check for json

request.format == 'json'
request.format == :json
request.format.json?
request.path.match('json')
request.url.match('json')
respond_to do |format|
  format.json { render json: [] }
end

You can also check if request was an ajax request

request.xhr?
like image 12
Cruz Nunez Avatar answered Nov 13 '22 20:11

Cruz Nunez