开发者

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 mydoma开发者_如何转开发in.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?


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.


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


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?


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


As easy as do:

request.path_parameters[:format] == 'json'


If you need to check if it was an Ajax request you can check for a header[X-Requested-With] using request.xhr?

Example code snippet

if request.xhr?
  # Do the ajax stuff
else
  # Do normal stuff
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜