Search code examples
jsonruby-on-rails-3.2activeresourceactioncontroller

Rails 3.2 - ActiveResource - Using POST/PUT with JSON


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

  1. It appears the Content-Type header must be explicitly set otherwise it results in a 415:Media Unrecognized error

  2. 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.


Solution

  • 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