【发布时间】:2022-01-08 20:49:53
【问题描述】:
我有一个非常简单的 Rails 6 控制器,叫做 BlogsController,有一个 UPDATE 动作,叫做 update。当我尝试使用邮递员提交 json 时,它返回 400 Bad Request,在日志中我发现只有一个???参数id,我的json内容被忽略了。这是非常基本的事情,应该有效,但它没有。这让我很困惑。请帮忙。
这是控制器代码:
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
我使用 PUT json 到 /blogs/1 将 Content-Type 标头设置为 application/json
Content-Type: application/json
要更新的项目如下所示:
{ "blog": {"id":1,"title":"Blog one","content":"Blog 1 Test Sem"} }
日志中的错误消息如下所示:
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'
正如您在日志中看到的,只有一个解析参数:{"id"=>"1"}。为什么JSON 内容主体被忽略?这简直太疯狂了,简直要死我了。
【问题讨论】:
-
我的建议是编写集成测试(如果您使用的是 RSpec,则请求规范) - 而不是使用 Postman。这样您就可以与我们分享它,我们可以重现结果。这也意味着您将时间花在防范未来的回归上,而不是让您的邮递员/卷发输入恰到好处,这浪费了时间。 99% 的时间它只是简单的用户错误,而您所做的对我们来说是一个黑匣子。
-
这里还有两个小东西 - PATCH is the primary method for updates since way back in 2012 但 Rails 仍然会生成 PUT 路由以实现向后兼容性,并且您不需要/不想在请求正文中传递 id,因为它是一部分网址。
标签: ruby-on-rails ruby-on-rails-5