Ruby on Rails 6 PUT json 参数未设置
Posted
技术标签:
【中文标题】Ruby on Rails 6 PUT json 参数未设置【英文标题】:Ruby on Rails 6 PUT json parameters are not set 【发布时间】: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,因为它是一部分网址。 【参考方案1】:我没有使用过 Postman,但我可以帮助您使用 cURL 将 JSON 数据提交到 Rails API。请在下面找到说明:
要发送 JSON,第一步是将 JSON 格式的数据(要发送到 API)放入一个文件中,例如 my_data.json
,并将其保存到一个位置,例如 /home/jignesh
,然后使用以下 cURL URL发送请求**:
curl -X PUT -H "Content-type: application/json" --data-binary @/home/jignesh/my_data.json "http://<API_URL>/blogs/<BLOG_ID>"
【讨论】:
【参考方案2】:根据日志,您正在 PUT 到 blogs/1
端点,而不是 blogs/1.json
。代码忽略了参数(也许邮递员没有正确发送它们 - 你没有表明你为此做了什么 - 但它们肯定被忽略了!)。我的假设是,通过 PUT 到 blogs/1
,您的代码会将其作为 blogs
的 PUT,参数 1
取自 URL。您的请求正文将被忽略。
【讨论】:
感谢您的建议。无论我 PUT 到 blogs/1 还是 blogs/1.json 都没有区别,都会抛出同样的错误。 好的,所以如果你在控制器顶部使用 byebug(或其他),那里的参数是什么样的。 (而不是依赖日志。)因为它是从某个地方得到1
的。如果您使用相同的 JSON 消息 PUT 到 blogs/2
会发生什么?
如果您查看日志,Rails 显然将请求视为 JSON。我会假设正在发送正确的内容类型。使用扩展只是设置请求格式的一种方式。以上是关于Ruby on Rails 6 PUT json 参数未设置的主要内容,如果未能解决你的问题,请参考以下文章
Bootstrap (5) Javascript 在 package.json 修订后不起作用 (Ruby on Rails 6)