I have a very simple Rails 6 controller called BlogsController, there is UPDATE action, called update. When I try to submit json using postman, it returns 400 Bad Request, in the logs I find that there is ONLY ONE ??? parameter id, my json content is ignored. This is very basic thing that should work and it doesn't. It confuses me. Please help.
This is controller code:
class BlogsController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :set_blog, only: %i[ show edit update destroy ]
# GET /blogs or /blogs.json
def index
@blogs = Blog.all
end
# GET /blogs/1 or /blogs/1.json
def show
end
# GET /blogs/new
def new
@blog = Blog.new
end
# GET /blogs/1/edit
def edit
end
# POST /blogs or /blogs.json
def create
@blog = Blog.new(blog_params)
respond_to do |format|
if @blog.save
format.html { redirect_to @blog, notice: "Blog was successfully created." }
format.json { render :show, status: :created, location: @blog }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @blog.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /blogs/1 or /blogs/1.json
def update
respond_to do |format|
if @blog.update(blog_params)
format.html { redirect_to @blog, notice: "Blog was successfully updated." }
format.json { render :show, status: :ok, location: @blog }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @blog.errors, status: :unprocessable_entity }
end
end
end
# DELETE /blogs/1 or /blogs/1.json
def destroy
@blog.destroy
respond_to do |format|
format.html { redirect_to blogs_url, notice: "Blog was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_blog
@blog = Blog.find(params[:id])
end
# Only allow a list of trusted parameters through.
def blog_params
params.require(:blog).permit(:title, :content)
end
end
I do PUT
json
to /blogs/1
with Content-Type header set to application/json
Content-Type: application/json
the item to update looks like this:
{ "blog": {"id":1,"title":"Blog one","content":"Blog 1 Test Sem"} }
error message in the logs looks like this:
2 [2] Started PUT "/blogs/1" for 54.86.50.139 at 2021-12-02 10:38:14 0000
2 [2] Processing by BlogsController#update as JSON
2 [2] Parameters: {"id"=>"1"}
2 heroku[router]: at=info method=PUT path="/blogs/1" host=ror-backend-angular-13.herokuapp.com request_id=2f1982a8-bbe1-41b0-bb3c-09b7e3db7caa fwd="54.86.50.139" dyno=web.1 connect=0ms service=7ms status=400 bytes=223 protocol=https
2 [2] Completed 400 Bad Request in 3ms (ActiveRecord: 0.9ms | Allocations: 441)
2 FATAL -- : [2]
2 [2] ActionController::ParameterMissing (param is missing or the value is empty: blog
2: Did you mean? action
2: controller
2: id):
2: [2]
2: [2] app/controllers/blogs_controller.rb:68:in `blog_params'
2 [2] app/controllers/blogs_controller.rb:41:in `block in update'
2 [2] app/controllers/blogs_controller.rb:40:in `update'
as you can see in the logs, there is only one parsed parameter: {"id"=>"1"}
. Why the JSON
content body is ignored? This is something completely crazy, it is killing me.
CodePudding user response:
I haven't used Postman but I can help you using cURL to submit JSON data to your Rails API. Please find the instructions below:
To send JSON the first step is to put the data (to be sent to the API) in its JSON format in a file say my_data.json
and save it to a location say /home/jignesh
and then use the following cURL URL to send the request**:
curl -X PUT -H "Content-type: application/json" --data-binary @/home/jignesh/my_data.json "http://<API_URL>/blogs/<BLOG_ID>"
CodePudding user response:
You're PUTting to the blogs/1
endpoint, not blogs/1.json
, according to the log. The code is ignoring the params (perhaps they're not being sent properly by Postman - you've not indicated what you've done on that end - but certainly they're ignored!). My assumption is that, by PUTting to blogs/1
you code is taking it as a PUT to blogs
with the parameter 1
taken from the URL. The body of your request is being ignored.