Reputation: 562
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: 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
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:
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'
Upvotes: 4
Views: 4738
Reputation: 3870
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
Upvotes: 6