当我将站点部署到 Heroku 时,控制器的 POST 方法停止工作

问题描述 投票:0回答:1

我在 Netlify 上部署了一个 [React 应用程序][1],其 [API 后端][2] (Ruby on Rails + PostgreSQL) 部署在 Heroku 上。后端在 LocalHost 上运行得非常好。然而,当我将其部署到 Heroku 时,我的三个控制器之一停止正常工作。我的所有其他控制器及其方法都是有效的,所以我不太明白为什么这个特定方法会失败。 Rails 控制台上的

Comment.create(...)
似乎也不起作用。

comment.rb(模型):

class Comment < ApplicationRecord
  belongs_to :User
  belongs_to :ForumThread
end

comments_controller.rb(控制器):

class CommentsController < ApplicationController
  #GET /Comments [Get all comments for a specific thread]
  def index
    @Comments = Comment.where("comments.forumthread_id = ?", params[:forum_thread_id])
    render json: @Comments
  end
  
  #GET /Comments/:id [Get a specific comment by its ID]
  def show
    @Comment = Comment.find(params[:id])
    render json: @comment
  end
  
  #POST /Comments [Create a comment]
  def create
    @comment = Comment.new(comment_params)
    if @comment.save
      render json: @comment
    else
      render error: {error: "Error in creating comment"}, status: 400
    end
  end
  
  #PUT /Comments/:id [Update a comment]
  def update
    @comment = Comment.find(params[:id])
    if @comment
      @comment.update(comment_params)
      render json: {message: "Comment successfully updated"}, status: 200
    else
      render error: {error: "Error in updating comment"}, status: 400
    end
  end
    
  #DELETE /Comments/:id [Delete a comment]
  def destroy
    @comment = Comment.find(params[:id])
    if @comment
      @comment.destroy
      render json: {message: "Comment successfully deleted"}, status: 200
    else
      render error: {error: "Error in deleting comment"}, status: 400
    end
  end
    
  private
  def comment_params
    params.require(:comment).permit(:forumthread_id, :User_id, :content)
  end
end

(GET 仍然有效,但 POST 已停止工作。我不确定其他方法,因为这些方法处理现有的评论,我无法创建)

schema.rb:

# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2023_01_17_054548) do
  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "comments", force: :cascade do |t|
    t.integer "User_id", null: false
    t.integer "forumthread_id", null: false
    t.string "content"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["User_id"], name: "index_comments_on_User_id"
    t.index ["forumthread_id"], name: "index_comments_on_forumthread_id"
  end

  create_table "forum_threads", force: :cascade do |t|
    t.integer "User_id", null: false
    t.string "title"
    t.string "description"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "tag"
    t.index ["User_id"], name: "index_forum_threads_on_User_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "username"
    t.string "email"
    t.string "password"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "bio"
  end
end

路线.rb:

Rails.application.routes.draw do
  #Routes
  get 'users/s/:username', to: "users#search"
  get 'users/:username/comments', to: "users#comments"
  resources :users, only: [:index, :show, :create, :update, :destroy]
  resources :forum_threads, only: [:index, :show, :create, :update, :destroy] do
    resources :comments, only: [:index, :show, :create, :update, :destroy]
  end
end

我的前端发送POST请求的函数:

const user_id = useSelector(state => state.id);
const threadID = useParams().id;
// console.log("Thread ID: ", threadID, "User ID: ", user_id, "Content: ", content);
//Creates new comment
const handleCreateComment = (event) => {
  if (!isContentError) {
    event.preventDefault();
    const requestOptions = {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ User_id: user_id, forumthread_id: threadID, content: content })
    };
    fetch('https://highgear.herokuapp.com/forum_threads/' + threadID + "/comments", requestOptions)
      .then(response => response.json())
      .then(data => refreshCreate(data))
      .catch(err => console.log(err));
  } else {
    event.preventDefault();
    window.alert("Error: Please enter a longer comment");
  }
}
(Even if forumthread_id, User_id, and content are all correct, it still doesn't work. Not to mention, it still worked on LocalHost).

Output of Heroku logs when I send a POST request:

2023-01-18T04:32:47.335761+00:00 app[web.1]: I, [2023-01-18T04:32:47.335689 #4]  INFO -- : [bd8c3745-fffc-485c-ba6d-42ff8dbfff91] Started POST "/forum_threads/1/comments" for 137.132.217.46 at 2023-01-18 04:32:47 +0000
2023-01-18T04:32:47.336418+00:00 app[web.1]: I, [2023-01-18T04:32:47.336374 #4]  INFO -- : [bd8c3745-fffc-485c-ba6d-42ff8dbfff91] Processing by CommentsController#create as */*
2023-01-18T04:32:47.336455+00:00 app[web.1]: I, [2023-01-18T04:32:47.336430 #4]  INFO -- : [bd8c3745-fffc-485c-ba6d-42ff8dbfff91]   Parameters: {"User_id"=>1, "forumthread_id"=>"1", "content"=>"<p>Test</p>", "forum_thread_id"=>"1", "comment"=>{"User_id"=>1, "forumthread_id"=>"1", "content"=>"<p>Test</p>"}}
2023-01-18T04:32:47.394387+00:00 app[web.1]: I, [2023-01-18T04:32:47.394318 #4]  INFO -- : [bd8c3745-fffc-485c-ba6d-42ff8dbfff91] Completed 400 Bad Request in 58ms (Views: 0.1ms | ActiveRecord: 36.8ms | Allocations: 3324)
2023-01-18T04:32:47.398408+00:00 heroku[router]: at=info method=POST path="/forum_threads/1/comments" host=highgear.herokuapp.com request_id=bd8c3745-fffc-485c-ba6d-42ff8dbfff91 fwd="137.132.217.46" dyno=web.1 connect=0ms service=60ms status=400 bytes=620 protocol=https

[Output in console logs][3]

  [1]: https://highgear.netlify.app
  [2]: https://highgear.herokuapp.com/
  [3]: https://i.stack.imgur.com/bMQrk.png

Here's the Heroku logs for a successful GET request to the comments controller:

2023-01-19T07:19:25.988821+00:00 heroku[router]: at=info method=GET path="/forum_threads/2/comments" host=highgear.herokuapp.com request_id=c9293482-735d-4039-8b40-842bd2bff8ce fwd="137.132.220.33" dyno=web.1 connect=0ms service=23ms status=304 bytes=612 protocol=https    
2023-01-19T07:19:25.924581+00:00 app[web.1]: I, [2023-01-19T07:19:25.924514 #4]  INFO -- : [5e0341e6-b66a-4a79-9d33-03050c8933c5] Started GET "/users/2" for 137.132.220.33 at 2023-01-19 07:19:25 +0000
2023-01-19T07:19:25.925293+00:00 app[web.1]: I, [2023-01-19T07:19:25.925219 #4]  INFO -- : [5e0341e6-b66a-4a79-9d33-03050c8933c5] Processing by UsersController#show as */*
2023-01-19T07:19:25.925308+00:00 app[web.1]: I, [2023-01-19T07:19:25.925285 #4]  INFO -- : [5e0341e6-b66a-4a79-9d33-03050c8933c5]   Parameters: {"id"=>"2"}
2023-01-19T07:19:25.927371+00:00 app[web.1]: I, [2023-01-19T07:19:25.927325 #4]  INFO -- : [5e0341e6-b66a-4a79-9d33-03050c8933c5] Completed 200 OK in 2ms (Views: 0.3ms | ActiveRecord: 0.5ms | Allocations: 271)
2023-01-19T07:19:25.964027+00:00 app[web.1]: I, [2023-01-19T07:19:25.963965 #4]  INFO -- : [c9293482-735d-4039-8b40-842bd2bff8ce] Started GET "/forum_threads/2/comments" for 137.132.220.33 at 2023-01-19 07:19:25 +0000
2023-01-19T07:19:25.964537+00:00 app[web.1]: I, [2023-01-19T07:19:25.964491 #4]  INFO -- : [c9293482-735d-4039-8b40-842bd2bff8ce] Processing by CommentsController#index as */*
2023-01-19T07:19:25.964565+00:00 app[web.1]: I, [2023-01-19T07:19:25.964537 #4]  INFO -- : [c9293482-735d-4039-8b40-842bd2bff8ce]   Parameters: {"forum_thread_id"=>"2"}
2023-01-19T07:19:25.986038+00:00 app[web.1]: I, [2023-01-19T07:19:25.985982 #4]  INFO -- : [c9293482-735d-4039-8b40-842bd2bff8ce] Completed 200 OK in 21ms (Views: 0.5ms | ActiveRecord: 20.1ms | Allocations: 210)

如果您需要更多信息,请评论。

编辑:以下是有关论坛线程模型的更多信息:

forum_threads_controller:

class ForumThreadsController < ApplicationController
  #GET /ForumThreads [Get all threads]
  def index
    @threads = ForumThread.all
    render json: @threads
  end
    
  #GET /ForumThreads/:id [Get a specific thread by its ID]
  def show
    @thread = ForumThread.find(params[:id])
    render json: @thread
  end

  #POST /ForumThreads [Create a thread] 
  def create
    @thread = ForumThread.new(thread_params)
    if @thread.save
      render json: @thread
    else
      render error: {error: "Error in creating thread"}, status: 400
    end
  end

  #PUT /ForumThreads/:id [Update a thread]
  def update
    @thread = ForumThread.find(params[:id])
    if @thread
      @thread.update(thread_params)
      render json: {message: "Thread successfully updated"}, status: 200
    else
      render error: {error: "Error in updating thread"}, status: 400
    end
  end

  #DELETE /ForumThreads/:id [Delete a thread]
  def destroy
    @thread = ForumThread.find(params[:id])
    @comments = Comment.where("ForumThread_id = ?", params[:id])
    if @thread
      for @comment in @comments
        @comment.destroy
      end
      @thread.destroy
      render json: {message: "Thread successfully deleted"}, status: 200
    else
      render error: {error: "Error in deleting thread"}, status: 400
    end
  end

  private
  def thread_params
    params.require(:forum_thread).permit(:User_id, :title, :description, :tag)
  end
end

forum_thread.rb:

class ForumThread < ApplicationRecord
  belongs_to :User
end
ruby-on-rails ruby postgresql heroku web-development-server
1个回答
0
投票

通过使用

@comment.save
并以相同的方式处理所有故障,您就隐藏了故障原因。

更好的方法是将

create
方法转换为:

    # POST /Comments [Create a comment]
    def create
      @comment = Comment.new(comment_params)
      @comment.save!
      render json: @comment
    rescue ArgumentError, ActiveRecord::RecordInvalid => err
      render error: {message: err.message }, status: 400
    rescue => err
      render error: {message: err.message }, status: 500
    end

但是这样做,您最终必须处理每条路线的失败案例。您希望为您的异常提供全局处理程序。示例:

class CommentsController < ApplicationController
    rescue_from Exception, with: :render_error
    rescue_from ArgumentError, with: :render_bad_request
    rescue_from ActiveRecord::RecordInvalid, with: :render_bad_request
    
    # ...
  
    # POST /Comments [Create a comment]
    def create
      @comment = Comment.new(comment_params)
      @comment.save!
      render json: @comment
    end

    # ...
    private 
     
    def render_bad_request(err)
      render error: {message: err.message }, status: 400
    end

    def render_error(err)
      render error: {message: err.message }, status: 500
    end
end

这些全局错误处理程序可以放入每个控制器继承的父类中,以使其更加可重用:

class BaseController < ApplicationController
    rescue_from Exception, with: :render_error
    rescue_from ArgumentError, with: :render_bad_request
    rescue_from ActiveRecord::RecordInvalid, with: :render_bad_request
    
    private 
     
    def render_bad_request(err)
      render error: {message: err.message }, status: 400
    end

    def render_error(err)
      render error: {message: err.message }, status: 500
    end
end

class CommentsController < BaseController
    # POST /Comments [Create a comment]
    def create
      @comment = Comment.new(comment_params)
      @comment.save!
      render json: @comment
    end
end
© www.soinside.com 2019 - 2024. All rights reserved.