0

I'm trying to follow this solution to add a params parser to my rails app, but all that happens is that I now get the headers but no parameters from the body of the JSON request at all. In other words, calling params from within the controller returns this:

{"controller"=>"residences", "action"=>"create", 
 "user_email"=>"wjdhamilton@wibble.com", 
 "user_token"=>"ayAJ8kDUKjCiy1r1Mxzp"}

but I expect this as well:

{"data"=>{"type"=>"residences", 
          "attributes"=>{"name-number"=>"The Byre", 
                         "street"=>"Next Door", 
                         "town"=>"Just Dulnain Bridge", 
                         "postcode"=>"PH1 3SY", 
                         "country-code"=>""}, 
          "relationships"=>{"residence-histories"=>{"data"=>nil}, 
                            "occupants"=>{"data"=>nil}}}}

Here is my initializer, which as you can see is almost identical to the one in the other post:

Rails.application.config.middleware.swap(
  ::ActionDispatch::ParamsParser, ::ActionDispatch::ParamsParser,
  ::Mime::Type.lookup("application/vnd.api+json") => Proc.new { |raw_post|

    # Borrowed from action_dispatch/middleware/params_parser.rb except for
    # data.deep_transform_keys!(&:underscore) :
    data = ::ActiveSupport::JSON.decode(raw_post)
    data = {:_json => data} unless data.is_a?(::Hash)
    data = ::ActionDispatch::Request::Utils.deep_munge(data)

    # Transform dash-case param keys to snake_case:
    data = data.deep_transform_keys(&:underscore)
    data.with_indifferent_access
  }
)

Can anyone tell me where I'm going wrong? I'm running Rails 4.2.7.1

Update 1: I decided to try and use the Rails 5 solution instead, the upgrade was overdue anyway, and now things have changed slightly. Given the following request:

"user_email=mogwai%40balnaan.com
&user_token=_1o3Kpzo4gTdPC2bivy
&format=json
&data[type]=messages&data[attributes][sent-on]=2014-01-15
&data[attributes][details]=Beautiful+Shetland+Pony
&data[attributes][message-type]=card
&data[relationships][occasion][data][type]=occasions
&data[relationships][occasion][data][id]=5743
&data[relationships][person][data][type]=people
&data[relationships][person][data][id]=66475"

the ParamsParser middleware only receives the following hash:

"{user":{"email":"mogwai@balnaan.com","password":"0h!Mr5M0g5"}}

Whereas I would expect it to receive the following:

{"user_email"=>"mogwai@balnaan.com", "user_token"=>"_1o3Kpzo4gTdPC2b-ivy", "format"=>"5743", "data"=>{"type"=>"messages", "attributes"=>{"sent-on"=>"2014-01-15", "details"=>"Beautiful Shetland Pony", "message-type"=>"card"}, "relationships"=>{"occasion"=>{"data"=> "type"=>"occasions", "id"=>"5743"}}, "person"=>{"data"=>{"type"=>"people", "id"=>"66475"}}}}, "controller"=>"messages", "action"=>"create"}

Community
  • 1
  • 1
James Hamilton
  • 457
  • 3
  • 16

1 Answers1

0

The problem was caused by the tests that I had written. I had not added the Content-Type to the requests in the tests, and had not explicitly converted the payload to JSON like so (in Rails 5):

post thing_path, params: my_data.to_json, headers: { "Content-Type" => "application/vnd.api+json }

The effects of this were twofold: Firstly, since params parsers are mapped to specific media types then withholding the media type meant that rails assumed its default media type (in this case application/json) so the parser was not used to process the body of the request. What confused me was that it still passed the headers to the parser. Once I fixed that problem, I was then faced with the body in the format of the request above. That is where the explicit conversion to JSON is required. I could have avoided all of this if I had just written accurate tests!

James Hamilton
  • 457
  • 3
  • 16