4

I'm trying to send a POST request from some client to a rails server and I'm having some problems.The full requirement is to send an image to to be processed by paperclip but it look like it's a general postman multipart POST with Rails problem.

This is what I'm getting: enter image description here Bellow my setup:

class CategoriesController < ApplicationController

def create
  @category = Category.new(category_params)

  respond_to do |format|
    if @category.save
      format.html { redirect_to @category, notice: 'Category was successfully created.' }
      format.json { render :show, status: :created, location: @category }
    else
      format.html { render :new }
      format.json { render json: @category.errors, status: :unprocessable_entity }
    end
  end
end
  private

    def category_params
      params.require(:category).permit(:label, :description)
    end

enter image description here

enter image description here

I'm assuming the problem is that the Request params are not encapsulated int the "categories". Please let me know if I wasn't clear enough and if I can offer more info.

Thanks in advance.

EDIT: As suggested by fylooi I've changed the Request Body in Postman adding an encapsulating "entity" like this: enter image description here

Still I'm getting the same results

    Processing by CategoriesController#create as JSON
  Parameters: {"------WebKitFormBoundaryFdJXZFMuAl0fZf3Q\r\nContent-Disposition: form-data; name"=>"\"category[label]\"\r\n\r\nTraffic\r\n------WebKitFormBoundaryFdJXZFMuAl0fZf3Q\r\nContent-Disposition: form-data; name=\"category[description]\"\r\n\r\nTraffic category\r\n------WebKitFormBoundaryFdJXZFMuAl0fZf3Q--\r\n"}
Completed 400 Bad Request in 1ms (ActiveRecord: 0.0ms)

ActionController::ParameterMissing (param is missing or the value is empty: category):
  app/controllers/categories_controller.rb:67:in `category_params'
  app/controllers/categories_controller.rb:27:in `create'
Lori
  • 562
  • 5
  • 24

1 Answers1

6

Postman works fine with Rails, you just need to understand how Rails handles parameters in general.

Let's say you POST the following parameters to the server:

plain_param=value
nested_object[attribute]=value

This gets parsed into the following:

pry(main)> params = ActionController::Parameters.new(plain_param:"value", nested_object: { attribute: "value" } )
=> {"plain_param"=>"value", "nested_object"=>{"attribute"=>"value"}}

Let's take a look at how permit works.

params.permit(:plain_param)
pry(main)> params.permit(:plain_param)
Unpermitted parameter: nested_object
=> {"plain_param"=>"value"}

pry(main)> params.permit(:nested_object)
Unpermitted parameters: plain_param, nested_object
=> {}

pry(main)> params.permit(:nested_object => :attribute)
Unpermitted parameter: plain_param
=> {"nested_object"=>{"attribute"=>"value"}}

pry(main)> params.permit(:plain_param, :nested_object => :attribute )
=> {"plain_param"=>"value", "nested_object"=>{"attribute"=>"value"}}

So far, so good. Looks like permit returns the entire hash for top level and nested permitted keys through and prints an alert for unpermitted keys. How about require?

[33] pry(main)> params
=> {"plain_param"=>"value", "nested_object"=>{"attribute"=>"value"}}

pry(main)> params.require(:plain_param)
=> "value"

pry(main)> params.require(:nested_object)
=> {"attribute"=>"value"}

pry(main)> params.require(:nested_object => :attribute)
ActionController::ParameterMissing: param is missing or the value is empty: {:nested_object=>:attribute}

pry(main)> params.require(:plain_param, :nested_object)
ArgumentError: wrong number of arguments (2 for 1)

We can see that require returns the value for a single param key. This comes in handy to ensure the presence of objects with multiple attributes.

Wrapping up:

params.require(:category).permit(:label, :description)

expects a hash of the form

{:category=>{:label=>"value", :description=>"value"}}

which translates to HTML POST parameters of

category[label]=value
category[description]=value

Edit: Postman automagically sets the content-type header for multi part file upload, so do not set it manually. Not sure whether this is considered a bug or a feature.

https://github.com/postmanlabs/postman-app-support/issues/191

fylooi
  • 3,840
  • 14
  • 24
  • Hello and thanks for you response. I allready tried setting the key names in Postman with category[{attribute}] but i'm still getting the same error. I will edit the question with this modification too.Thanks – Lori Aug 27 '15 at 09:47
  • @Lori: Add `puts params` before the `params.require...` line and post the log output? – fylooi Aug 27 '15 at 10:53
  • This is how the params looks: {"------WebKitFormBoundaryaH47lDnnoGYytZoO\r\nContent-Disposition: form-data; name"=>"\"category[label]\"\r\n\r\nTraffic\r\n------WebKitFormBoundaryaH47lDnnoGYytZoO\r\nContent-Disposition: form-data; name=\"category[description]\"\r\n\r\nTraffic category\r\n------WebKitFormBoundaryaH47lDnnoGYytZoO--\r\n", "controller"=>"categories", "action"=>"create"} – Lori Aug 27 '15 at 10:58
  • @Lori: Is this printed by `puts params`? – fylooi Aug 27 '15 at 11:04
  • Also, did you make any changes to the default headers in Postman? – fylooi Aug 27 '15 at 11:12
  • Yes, thats the result of puts params. The headers are those shown in the picture with postman. Thanks again – Lori Aug 27 '15 at 11:20
  • @Lori: Looks like that's what's messing with the param parsing. Postman will handle the multipart headers for you if one of your parameters is a file. Clear the custom headers and it should work. – fylooi Aug 27 '15 at 11:27
  • So you are saying that because I'm not including a file Postman doesn't build the request properly? I tried adding an image file to the request Body under category[image]. This is what I'm seeing in the logs {Processing by CategoriesController#create as JSON THE PARAMS ARE: {"controller"=>"categories", "action"=>"create"} Completed 400 Bad Request in 1ms (ActiveRecord: 0.0ms) ActionController::ParameterMissing (param is missing or the value is empty: category): app/controllers/categories_controller.rb:70:in `category_params' app/controllers/categories_controller.rb:28:in `create'} – Lori Aug 27 '15 at 12:11
  • Note that the params are missing and that rails usually prints the parameters under "Processing by CategoriesController#create as JSON " but not this time. This is really strange. – Lori Aug 27 '15 at 12:13
  • 2
    Postman will add the `content-type=multipart` header if you include a file. You don't need to add it manually. The multipart notation should be the reason why Rails is unable to parse the request properly. – fylooi Aug 27 '15 at 12:20
  • Ok, so I removed the Content-type header, and put the image parameter in the body and it works. For me this means that the "Content-Type:multipart/form-data" i entered in Postman is wrong. Or maybe this could be accounted as a postman bug? @fylooi THANK YOU – Lori Aug 27 '15 at 12:25
  • please add these findings to your answer maybe with a link to this https://github.com/postmanlabs/postman-app-support/issues/191 and I will accept your answer. Thanks a lot. Edit: this is also helpfull http://stackoverflow.com/questions/19178813/sending-multipart-mixed-content-with-postman-chrome-extension – Lori Aug 27 '15 at 12:42