{“user”:[“必须存在”]} Rails嵌套资源和身份验证时出错

时间:2017-08-10 03:14:51

标签: ruby-on-rails

我对Rails相对较新,并且我认为这是一个我想要使用的相对简单的设置。我有用户,列表和项目。每个用户都有许多列表,每个列表都有很多项。登录后我无法创建项目。

用户模型:

class User < ApplicationRecord
  include Authentication
  has_many :examples
  has_many :lists
  has_many :items
end

列表模型:

class List < ApplicationRecord
  belongs_to :user
  has_many :items
end

物品型号:

class Item < ApplicationRecord
  belongs_to :user
  belongs_to :list
end

以下是相关路线:

Rails.application.routes.draw do
  resources :lists do
    resources :items
  end

我可以使用以下控制器创建/读取/更新/删除列表:

class ListsController < ProtectedController
  before_action :set_list, only: [:show, :update, :destroy]

  # GET /lists
  def index
    @lists = current_user.lists

    render json: @lists
  end

  # GET /lists/1
  def show
    render json: List.find(params[:id])
  end

  # POST /lists
  def create
    @list = current_user.lists.build(list_params)

    if @list.save
      render json: @list, status: :created, location: @list
    else
      render json: @list.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /lists/1
  def update
    if @list.update(list_params)
      render json: @list
    else
      render json: @list.errors, status: :unprocessable_entity
    end
  end

  # DELETE /lists/1
  def destroy
    @list.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_list
      @list = current_user.lists.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def list_params
      params.require(:list).permit(:name)
    end
end

但是,我无法成功创建项目。这是我的项目控制器:

class ItemsController < ProtectedController
  before_action :set_item, only: [:show, :update, :destroy]

  # GET /items
  def index
    @items = current_user.items

    render json: @items
  end

  # GET /items/1
  def show
    render json: @item
  end

  # POST /items
  def create
    @list = List.find(params[:list_id])
    @item = @list.items.create(item_params)

    if @item.save
      render json: @item, status: :created, location: @item
    else
      render json: @item.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /items/1
  def update
    if @item.update(item_params)
      render json: @item
    else
      render json: @item.errors, status: :unprocessable_entity
    end
  end

  # DELETE /items/1
  def destroy
    @item.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_item
      @item = current_user.items.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def item_params
      params.require(:item).permit(:name, :quantity, :price, :store, :category, :notes, :user_id, :list_id)
    end
end

我登录,创建一个列表,然后尝试将项目发布到该列表但得到以下错误: {"user":["must exist"]}

以下是来自服务器的消息:

Started POST "/lists/4/items" for 127.0.0.1 at 2017-08-09 22:47:19 -0400
Processing by ItemsController#create as */*
  Parameters: {"item"=>{"name"=>"Test Item", "quantity"=>"1", "price"=>"9.99", "store"=>"Fruit Center", "category"=>"Dairy", "notes"=>"Important Note"}, "list_id"=>"4"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."token" = $1 LIMIT $2  [["token", "27e3e2a67d86cb9d3f46d20651370b74"], ["LIMIT", 1]]
  List Load (0.3ms)  SELECT  "lists".* FROM "lists" WHERE "lists"."id" = $1 LIMIT $2  [["id", 4], ["LIMIT", 1]]
   (0.1ms)  BEGIN
   (0.2ms)  COMMIT
   (0.1ms)  BEGIN
   (0.1ms)  ROLLBACK
[active_model_serializers] Rendered ActiveModel::Serializer::Null with ActiveModel::Errors (0.06ms)
Completed 422 Unprocessable Entity in 8ms (Views: 0.5ms | ActiveRecord: 1.1ms)

或者,我尝试将项目的创建操作更改为:

  def create
    @item = current_user.items.create(item_params)

    if @item.save
      render json: @item, status: :created, location: @item
    else
      render json: @item.errors, status: :unprocessable_entity
    end
  end

这样做会导致错误略有不同:{"list":["must exist"]}

从服务器:

Started POST "/lists/4/items" for 127.0.0.1 at 2017-08-09 23:09:20 -0400
Processing by ItemsController#create as */*
  Parameters: {"item"=>{"name"=>"Test Item", "quantity"=>"1", "price"=>"9.99", "store"=>"Fruit Center", "category"=>"Dairy", "notes"=>"Important Note"}, "list_id"=>"4"}
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."token" = $1 LIMIT $2  [["token", "27e3e2a67d86cb9d3f46d20651370b74"], ["LIMIT", 1]]
   (0.1ms)  BEGIN
   (0.2ms)  COMMIT
   (0.1ms)  BEGIN
   (0.1ms)  ROLLBACK
[active_model_serializers] Rendered ActiveModel::Serializer::Null with ActiveModel::Errors (0.07ms)
Completed 422 Unprocessable Entity in 32ms (Views: 2.2ms | ActiveRecord: 4.1ms)

看起来list_id确实在参数中传递,但是它没有在create方法中被拾取。

我觉得我可能会遗漏一些简单的东西。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

请在日志中注意list_id不在item参数内:

Parameters: {"item"=>{"name"=>"Test Item", "quantity"=>"1", "price"=>"9.99", "store"=>"Fruit Center", "category"=>"Dairy", "notes"=>"Important Note"}, "list_id"=>"4"}

params[:list_id] # => 4
params[:item][:list_id] # => nil

您在params[:item][:list_id]中列出了item_params白名单,但list_id未嵌套在params[:item]中,因为在您的项目表单中您没有要传递的字段(需要使用name='item[list_id]'的表单输入)。而是基于路由params[:list_id] = 4为请求设置/lists/4/items。你可以做到

def create
  @item = current_user.items.build(item_params)
  @item.list_id = params[:list_id]

  if @item.save
    render json: @item, status: :created, location: @item
  else
    render json: @item.errors, status: :unprocessable_entity
  end
end

请注意,我已拨打current_user.items.build而非current_user.items.create。使用current_user.items.create将尝试立即保存您不希望在这种情况下执行的记录(似乎)。