Rails 3.2 - ActiveResource - Using POST/PUT with JSON
Asked Answered
J

2

6

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.

Jobholder answered 23/5, 2012 at 21:8 Comment(2)
So I "fixed" this by overriding the to_json method in my model to simply return self.attributes.to_json - however, if anyone has ideas as to why the include_root_in_json configuration is not working, I am still very curious as I find that configuration would be a more elegant solution. Thanks!Jobholder
You might want to add the solution as answer and accept it...Steinke
J
1

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
Jobholder answered 10/10, 2012 at 19:25 Comment(0)
S
1

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

Shuffleboard answered 11/5, 2013 at 3:31 Comment(1)
3-2-stable has merged this patch pull request. The next version 3.2.14 will include this fix.Shuffleboard

© 2022 - 2024 — McMap. All rights reserved.