Home > Back-end >  Ruby on Rails 6 PUT json parameters are not set
Ruby on Rails 6 PUT json parameters are not set

Time:12-04

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.

  • Related