Read more

XHR is not JSON

Arne Hartherz
January 18, 2018Software engineer at makandra GmbH

The xhr? method relies on a header that is no longer sent by modern HTTP clients.

When a Rails controller action should handle both HTML and JSON responses, do not use request.xhr? to decide that. Use respond_to.

Illustration UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
Read more Show archive.org snapshot

I've too often seen code like this:

def show
  # ...
  if request.xhr?
    render json: @user.as_json
  else
     # renders default HTML view
  end
end

This is just plain wrong. Web browsers often fetch JSON via XHR, but they (should) also send the correct Accept HTTP header to tell the server the data they expect to receive.

If you say request.xhr? as a means for "wants JSON" you are locking out any client applications that correctly send Accept: application/json as a "regular" (non-XHR) request. And you are messing up responses for XHRs that want to load something else (like HTML views in Unpoly Show archive.org snapshot ).

Your actions should choose the response format via the respond_to method:

def show
  # ...
  respond_to do |format|
    format.html # renders default HTML view
    format.json { render json: @user.as_json }
  end
end

If your JSON is a bit more complex than the example above, you should put it into its own view (e.g. show.json.jbuilder). You can then refer to both views in your controller:

def show
  # ...
  respond_to :html, :json
end
Posted by Arne Hartherz to makandra dev (2018-01-18 10:24)