我对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方法中被拾取。
我觉得我可能会遗漏一些简单的东西。有什么想法吗?
答案 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
将尝试立即保存您不希望在这种情况下执行的记录(似乎)。