#ruby-on-rails #ruby-on-rails-5
#ruby-on-rails #ruby-on-rails-5
Вопрос:
У меня есть очень простой контроллер Rails 6 под названием BlogsController, есть действие ОБНОВЛЕНИЯ, называемое update . Когда я пытаюсь отправить json с помощью postman, он возвращает 400 неверных запросов, в журналах я нахожу, что есть ТОЛЬКО ОДИН??? идентификатор параметра, мое содержимое 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
это с заголовком типа содержимого, установленным в 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
тело содержимого игнорируется? Это что-то совершенно сумасшедшее, это убивает меня.
Комментарии:
1. Мой совет — написать интеграционный тест (или запросить спецификацию, если вы используете RSpec) — вместо использования Postman. Таким образом, вы можете поделиться им с нами, и мы сможем воспроизвести результаты. Это также означает, что вы тратите свое время на защиту от будущих регрессий вместо того, чтобы правильно использовать входные данные postman / curl, что является пустой тратой времени. в 99% случаев это просто ошибка пользователя, и то, что вы делаете со своей стороны, является для нас черным ящиком.
2. Здесь также есть две небольшие однотипные вещи — PATCH является основным методом обновления с 2012 года, но Rails по-прежнему генерирует маршруты PUT для обратной совместимости, и вам не нужно / не нужно передавать идентификатор в теле запроса, поскольку он является частью URL.
Ответ №1:
Я не использовал Postman, но я могу помочь вам с помощью cURL для отправки данных JSON в ваш Rails API. Пожалуйста, ознакомьтесь с инструкциями ниже:
Для отправки JSON первым шагом является помещение данных (для отправки в API) в формате JSON в файл, скажем my_data.json
, и сохранение его в местоположение, скажем /home/jignesh
, а затем использование следующего URL-адреса cURL для отправки запроса**:
curl -X PUT -H "Content-type: application/json" --data-binary @/home/jignesh/my_data.json "http://<API_URL>/blogs/<BLOG_ID>"
Ответ №2:
Вы отправляете в blogs/1
конечную точку, а не blogs/1.json
в соответствии с журналом. Код игнорирует параметры (возможно, они не отправляются почтальоном должным образом — вы не указали, что вы сделали с этой целью, но, конечно, они игнорируются!). Я предполагаю, что, передавая blogs/1
вам код, вы принимаете его как PUT to blogs
с параметром 1
, взятым из URL. Тело вашего запроса игнорируется.
Комментарии:
1. спасибо за ваше предложение. Независимо от того, ПОМЕЩАЮ ли я в blogs /1 или blogs / 1.json, не имеет значения, выдается та же ошибка.
2. Хорошо, итак, если вы используете byebug (или что-то еще) в верхней части вашего контроллера, как там выглядят параметры. (Вместо того, чтобы полагаться на журнал.) Потому что это
1
откуда-то берется. Что произойдет, если вы ВВЕДЕТЕ toblogs/2
с тем же сообщением JSON?3. Если вы посмотрите на журнал, Rails явно обрабатывает запрос как JSON. Я бы предположил, что отправляется правильный тип контента. Использование расширения — это только один из способов установки требуемого формата.