Reputation: 4750
I've built an Rails app that is called by another one (Rails as well), using ActiveResource.
The situation is that I expose the info from the first app as JSON as follows:
App 1:
class PromotionsController < ApplicationController
# GET /promotions
# GET /promotions.xml
def index
@promotions = Promotion.all
respond_to do |format|
format.json { render :json => @promotions }
end
end
end
And I receive it on the App 2, through an ActiveResource model, as follows:
class Promotion < ActiveResource::Base
self.site = "app_1_url"
self.element_name = "promotion"
end
When I want to read the data as JSON, doing the following, I get 406 Not Acceptable error message:
class PromotionsController < ApplicationController
# GET /promotions
# GET /promotions.xml
def index
@promotions = Promotion.all
respond_to do |format|
format.json { render :json => @promotions }
end
end
end
But, when I try to parse the info as XML (doing the same as the code shown above, except for changing "json" for "xml" everywhere) it works.
Any ideas?
Thanks.
Upvotes: 0
Views: 2924
Reputation: 5376
In addition to CoryDanielson's answer.
Even when my application is using :xml format (which is as Cory noted set by default) I still had to include
self.format = :xml
in order to fix 406 error.
Upvotes: 1
Reputation: 14501
You have to change the format to JSON for the application that is receiving the data (App 2)
class Promotion < ActiveResource::Base
#your code
self.format = :json #XML is default
end
Here's how I went about figuring that out (for any googlers that end up here)
Per Wikipedia:
406 Not Acceptable
The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.
(Basically, the data you received is in a different language than you wanted)
Because a 400 level error code is a Client error code, I determined that the error must have been with App 2 (in this case, app 2 is the client requesting data from app 1). I saw that you were doing some formatting for JSON in app 1 and looked for similar code in App 2 and didn't see it, so I assumed the error was with App 2 having a different Content-Type header than App 1. The Content-Type basically tells applications/browsers what language each is speaking when they send/receive data. The value that you store in the Content-Type is the MIME Type and there are lots of them.
You said that the XML type worked but JSON wasn't, so I checked the rails ActiveResource API (used in App 2) looking for some headers or content-type method and saw a format
method and property which matches what you used in the Action Controller for App 1. I also saw that the format
is defaulted to XML if it is not supplied.
#Returns the current format, default is ActiveResource::Formats::XmlFormat.
def format
read_inheritable_attribute(:format) || ActiveResource::Formats[:xml]
end
add this line to the class in app 2:
self.format = :json
I'm sure you could adjust the Content-Type header with the headers method as well, but the API didn't have sample code displaying how to do that. Adjusting the Content-Type with the headers method would kind of just be the 'harder' way to do it, and because adjusting the Content-Type is so common rails created format
to streamline the process. I saw that the API has an example of adjusting the format attribute of the class that conveniently uses json and read that the format
method/property "Sets the format
that attributes are sent and received in from a mime type reference" aka sets the Content-Type HTTP Header.
Upvotes: 5