简体   繁体   中英

Why am I getting a “Completed 406 Not Acceptable” when a POST request is made in my Rails 5 app?

A bit of context. I'm creating an API that is contacted by an external server. This server contacts the API with POST requests to the endpoint /vehicles with a unique id number. The request body has the format { "id": “some_string_here” }. My API stores these in the db. After the vehicles have been created the external server then makes POST requests with the endpoint vehicles/:id/locations with the request body looking something like this { "lat": 23.0, "lng": 30.0, "at": "2018-09-02T07:00:00Z" } - adding lat lng coordinates and a time stamp to each vehicle periodically (to update the vehicle's location).

I have been able to set up my API with vehicles and locations controllers and when I start the external server the vehicles are stored successfully. The problem I have is when the server then starts to send POST requests to add locations to each vehicle. I get the error:

Started POST "/vehicles/a38edd77-07b0-4069-8a1d-462428989ecf/locations" for 127.0.0.1 at 2019-07-29 13:53:21 +0200
Processing by LocationsController#create as HTML
  Parameters: {"lat"=>52.44339, "lng"=>13.24326, "at"=>"2019-07-29T11:53:20.044Z", "vehicle_id"=>"a38edd77-07b0-4069-8a1d-462428989ecf", "location"=>{"lat"=>52.44339, "lng"=>13.24326, "at"=>"2019-07-29T11:53:20.044Z"}}
  Vehicle Load (0.9ms)  SELECT  "vehicles".* FROM "vehicles" WHERE "vehicles"."unique_id" = $1 LIMIT $2  [["unique_id", "a38edd77-07b0-4069-8a1d-462428989ecf"], ["LIMIT", 1]]
  ↳ app/controllers/locations_controller.rb:10
   (0.7ms)  BEGIN
  ↳ app/controllers/locations_controller.rb:15
   (2.4ms)  ROLLBACK
  ↳ app/controllers/locations_controller.rb:15
Completed 406 Not Acceptable in 12ms (Views: 0.2ms | ActiveRecord: 4.0ms)

ActionController::UnknownFormat (ActionController::UnknownFormat):

Any idea what could fix this? Any help would be much appreciated. My code is below.

controllers/vehicles_controller.rb:

class VehiclesController < ApplicationController

  def index
    @vehicles = Vehicle.all
    render json: @vehicles
  end

  def create
    @vehicle = Vehicle.new(vehicle_params)

    respond_to do |format|
      if @vehicle.save
      render json: @vehicle, status: :created, location: @vehicle
    else
      render json: @vehicle.errors, status: :unprocessable_entity
    end
    end
  end

  def destroy
    @vehicle.destroy
    respond_to do |format|
      format.json { head :no_content }
    end
  end

  private

    def vehicle_params
      # swap id column value with unique_id to avoid conflict with primary key
      params[:vehicle][:unique_id] = params[:vehicle].delete(:id)
      params.require(:vehicle).permit(:unique_id)
    end
end

controller/locations_controller.rb

class LocationsController < ApplicationController

  def index
    @locations = Location.all
    render json: @locations
  end

  def create
    @vehicle = Vehicle.find_by!(unique_id: params[:vehicle_id])
    @location = @vehicle.locations.new(location_params)


    respond_to do |format|
      if @location.save
      render json: @location, status: :created, location: @location
    else
      render json: @location.errors, status: :unprocessable_entity
    end
    end
  end

  private

    def location_params
      params.require(:location).permit(:lat, :lng, :at, :vehicle_id)
    end
end

vehicle.rb

class Vehicle < ApplicationRecord
  has_many :locations
end

location.rb

class Location < ApplicationRecord
  belongs_to :vehicles
end

routes.rb

Rails.application.routes.draw do
  resources :vehicles do
    resources :locations
  end
end

schema.rb

ActiveRecord::Schema.define(version: 2019_07_27_224818) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "locations", force: :cascade do |t|
    t.float "lat"
    t.float "lng"
    t.datetime "at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "vehicle_id"
  end

  create_table "vehicles", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "unique_id"
  end

end

As long your server is working as API you should skip CSRF token authenticity verification

class LocationsController < ApplicationController

   skip_before_action :verify_authenticity_token

   ...

Also it seems you have error in relations

class Location < ApplicationRecord
  belongs_to :vehicles <-- should be :vehicle here
end

Try using save! instead of save and see what's the error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM