I have been looking at this for a while, and am currently at a loss. I have narrowed the problem down to being related to JSON, and that the JSON does not appear to be being sent in a legible format.
We were previously using Rails 3.0.7 (where the problem I am about to describe did NOT exist). We need to upgrade Rails to take advantage of some new functionality - but now there is this issue. I am almost sure at this point it is a simple configuration or something, but I need some more eyes on it.
We are using ActiveResource objects, and upon setting the values of the object and saving it (thus making a PUT), we get ab 403:Forbidden returned from the remote web service. This is not a problem on the web service layer.
Upon creating a new object and making a POST, we are getting a 409:Conflict returned as it tries to update the database with default values - thus meaning the json data is not reaching the service - or is not legible.
My issue is that this worked in Rails 3.0.7, and no longer works in 3.2.3 (or 3.1.3 which I also tried). I am open to suggestions other than the JSON data, however I am pretty sure that that is where the issue is.
My ActiveResource model has
self.format = :json
I have the following in one of my initializer files:
ActiveResource::Base.include_root_in_json = false
ActiveSupport::JSON.backend = "json_gem"
Thanks for any suggestions!
UPDATE
I have been testing out with curl and got it to work by:
curl -H "Content-Type: application/json" -d "{\"userID\":\"xxx\", \"label\":\"doc.test.test\", \"value\":\"1,19\", \"id\":\"-1\"}" -v -X POST http://host:port/usermanagement/users/xxx/prefs
I got that to work, but
It appears the Content-Type header must be explicitly set otherwise it results in a 415:Media Unrecognized error
If I set the Content-Type header in the ActiveResource object, I still get the 409:Conflict error - which leads me to believe the JSON is still not properly formed.
EDIT (Again)
I have figured out where the issue with the JSON is - Rails is keeping the root in the JSON. Thus instead of sending the resource back as
{"name":"value", "name":"value"}
It is sending
{"ResourceName": {"name":"value", "name":"value"}}
However, I have set include_root_in_json
to false - I tried this both in the initializer files, and directly in the model itself, and no change.
So I "fixed" this (worked around it) by overriding the to_json
method in my model to simply return self.attributes.to_json
class Document < ActiveResource::Base
self.site += 'user/:user_id'
self.element_name = "docs"
def to_json(options={})
self.attributes.to_json(options)
end
end
Looks like ActiveResource::Base.include_root_in_json is broken in Rails 3-2-stable (including 3.2.13). This issue has been fixed in the standalone activeresource repo:
def to_json(options={})
super(include_root_in_json ? { :root => self.class.element_name }.merge(options) : options)
end
You can monkey patch it in one of your initializers by doing the same thing.
Update: This issue has been fixed in rails 3-2-stable backport commit
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With