为什么我得到这个`ActiveRecord :: RecordNotFound。 (找不到'id')`我的Rails API中的POST请求出错?

时间:2019-07-28 19:04:51

标签: ruby-on-rails ruby

某些上下文。我正在创建一个由外部服务器联系的API。该外部服务器使用唯一的ID号向端点/vehicles发送POST请求来联系API。请求正文的格式为{ "id": “some_string_here” }。我的API将这些存储在db中。在创建车辆之后,外部服务器将向端点vehicles/:id/locations发出POST请求,请求主体看起来像这样{ "lat": 10.0, "lng": 20.0, "at": "2019-09-01T12:00:00Z" }-向每辆车辆定期添加纬度坐标和时间戳(以进行更新)车辆的位置)。

我已经能够使用vehicleslocations控制器设置我的API,并且当我启动外部服务器时,车辆已成功存储。我的问题是服务器随后开始发送请求以将位置添加到每辆车时。在控制台中,我收到消息:

Processing by LocationsController#create as HTML

  Parameters: {"lat"=>52.44381, "lng"=>13.47686, "at"=>"2019-07-28T16:56:45.311Z", "vehicle_id"=>"d759fc35-b25c-4877-8e40-9b0104447b31", "location"=>{"lat"=>52.44381, "lng"=>13.47686, "at"=>"2019-07-28T16:56:45.311Z"}}
ActiveRecord::RecordNotFound (Couldn't find Vehicle with 'id'=d6880741-ae7f-4741-aa04-950b0a1e2d3b):
Can't verify CSRF token authenticity.

app/controllers/locations_controller.rb:9:in `create'
  Vehicle Load (38.2ms)  SELECT  "vehicles".* FROM "vehicles" WHERE "vehicles"."id" = $1 LIMIT $2  [["id", 0], ["LIMIT", 1]]
  ↳ app/controllers/locations_controller.rb:9
Completed 404 Not Found in 50ms (ActiveRecord: 38.2ms)

ActiveRecord::RecordNotFound (Couldn't find Vehicle with 'id'=d759fc35-b25c-4877-8e40-9b0104447b31):

该问题可能与以下事实有关:存储车辆的请求具有id作为主体中的键(与默认主键列名称相同的名称)。这意味着我必须为服务器通过的车辆ID创建一个新列,然后在控制器中添加以下代码以更改params哈希值:

def vehicle_params
  params[:vehicle][:unique_id] = params[:vehicle].delete(:id)
end 

这意味着车辆已正确存储,但是这可能是(也可能不是)我收到上述错误消息的原因。有什么想法我可以解决这个问题吗?我的相关代码如下。

vehicles_controller.rb

class VehiclesController < ApplicationController
...
  def create
    @vehicle = Vehicle.new(vehicle_params)

    respond_to do |format|
      if @vehicle.save
        format.json { render status: :created, location: @vehicle }
      else
        format.json { render json: @vehicle.errors, status: :unprocessable_entity }
      end
    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

locations_controller.rb

class LocationsController < ApplicationController
...
  def create
    @vehicle = Vehicle.find(params[:vehicle_id])
    @location = @vehicle.locations.new(location_params)


    respond_to do |format|
      if @location.save
        format.json { render :show, status: :created, location: @vehicle }
      else
        format.json { 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

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

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:1)

看起来字符串d6880741-ae7f- ....对应于车辆上的unique_id列。在这种情况下,您将使用

@vehicle = Vehicle.find_by!(unique_id: params[:vehicle_id])

id列是一个int,而params[:vehicle_id]是一个字符串...因此,Vehicle.find(params[:vehicle_id])总是会引发“未找到”错误,这就是您所看到的行为

请注意,如果找不到记录,则findfind_by!会引发错误。如果您不希望发生这种情况,则可以使用find_by(不带感叹号)-如果找不到记录,它只会返回nil。但是您必须更改代码以解决@vehicle为零的可能性。

答案 1 :(得分:0)

我看到模式vehicle_id是一个整数,但是来自日志ia字符串的请求为:“ d759fc35-b25c-4877-8e40-9b0104447b31”。这是不是字符串无法保存到整数列的问题?

答案 2 :(得分:0)

您能否提供从铁轨出发的路线?请从控制台执行。

rake routes

告诉我们,车辆资源中的参数是什么?也许问题是路由中的参数与控制器不匹配?