fetch 的双命名空间路由问题

问题描述

Hello> 我正在创建一个包含书籍和用户的 Javascript SPA/Rails Api。我在我的路由中使用命名空间,以及每个模型的序列化程序。我不确定为什么在尝试为用户执行 post fetch 请求时会收到此错误。我不确定我的书是否会遇到同样的问题。 Belo 你可以看到我的控制器顶部的每个控制器都有 Api::V1....etc 的位置。然后我在我的路由中有我的命名空间路由。我的 rails 控制台也在运行

路由错误 未初始化的常量 Api

我的控制器

class Api::V1::UsersController < ApplicationController

    def index
        users=User.all
        render json: users
    end 

    def create
        if User.find_by(:name=> user_params[:name])
            user=User.find_by(:name=>user_params[:name])
            redirect_to "/api/v1/users/#{user.id}"
        else 
            user = User.create(user_params)
            user.save!
            render json: user
        end 
    end 

    def show
        user = User.find_by(:id => params[:id])
        render json: user
    end 

    private

    def user_params
        params.require(:user).permit(:name)
    end
end
class Api::V1::BooksController < ApplicationController

    def index
        books = Book.all
        render json: books
    end 

    def create
        book = Book.create(book_params)
        book.save!
        render json: book
    end 

    def destroy
        book=Book.find_by(:id => params[:id]).destroy
        render json: book
    end 

    private

    def book_params
        params.require(:book).permit(:title,:author,:review,:rating,:user_id)
    end 
end

路线

Rails.application.routes.draw do






  namespace :api do
    namespace :v1 do
      resources :books
    end
  end
end
//POST fetch for creating a User
    static createuser(user) {
        let newUserForm = document.getElementById('new-user-form')
        newUserForm.addEventListener('submit',function(e){
            e.preventDefault();
            fetch('http://localhost:3000/api/v1/users',{
                method: 'POST',headers: {
                    'Content-Type' : 'application/json','Accept' : 'application/json'
                },body: JSON.stringify({
                    user: {
                        name: e.target.children[1].value
                    }
                })
            })
                .then(res => {
                    if (!res.ok) {
                        throw new Error(); // Will take you to the `catch` below
                    }
                    return res.json();
                })
                .then (user => {
                    let newUser = new User(user)
                    console.log(user)
                    newUser.displayUser();
                })
                .catch(error => {
                    console.error('User class Error',error)
                })
            })
    }

解决方法

使用显式定义(并重新打开)命名空间的类和模块 嵌套。使用范围解析运算符可能会导致令人惊讶的结果 由于 Ruby 的词法范围而导致的持续查找,这取决于 模块在定义点嵌套。

module Api
  module V1
    class UsersController < ApplicationController
      # ...
    end
  end 
end

虽然您可能天真地相信 class Api::V1::UsersController 会做同样的事情,但事实并非如此,因为它需要在加载类时定义 Api 模块,并且没有正确设置模块嵌套,这将导致令人惊讶不断的查找。例如,当您使用 User 时,Ruby 不会像预期的那样找到 Api::UserApi::V1::User

然而,这段代码还有更多问题,因为它充斥着糟糕的 api 设计决策——潜在的零错误(通过使用 find_by 而不是 find)。它应该看起来像这样:

# no need to repeat yourself
namespace :api do
  namespace :v1 do
    resources :users
    resources :books
  end 
end
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym 'API'
end
# Acronyms should be all-caps
# https://github.com/rubocop-hq/ruby-style-guide#camelcase-classes
module API
  module V1
    class UsersController < ApplicationController
      
      # GET /api/v1/users
      def index
        users = User.all
        render json: users
      end 

   
      # POST /api/v1/users
      def create
        user = User.new(user_params)
        if user.save
          render json: user,status: :created
        else
          render json: { errors: user.errors.full_messages },status: :unprocessable_entity
        end
      end 
      
      # GET /api/v1/users/1
      def show
        # Use .find instead of find_by as it will return a
        # 404 - Not Found if the user is not found
        user = User.find(params[:id])
        render json: user
      end 
      
      private
      
      def user_params
        params.require(:user).permit(:name)
      end
    end
  end 
end
module API
  module V1
    class BooksController < ApplicationController
      # GET /api/v1/books
      def index
        books = Book.all
        render json: books
      end

      # POST /api/v1/books
      def create
        book = Book.new(book_params)
        if book.save
          render json: book,status: :created
        else 
          render json: { errors: book.errors.full_messages },status: :created
        end
      end

      # DELETE /api/v1/books/1
      def destroy
        book = Book.find(params[:id])
        book.destroy
        head :ok 
      end

      private

      def book_params
        params.require(:book)
              .permit(:title,:author,:review,:rating,:user_id)
      end
    end
  end
end

创建资源时,如果成功,您应该返回 201 CREATED 响应,并在响应正文中包含资源或提供一个位置标头,告诉客户端他们可以在哪里找到资源。

如果它不成功,您应该返回一个状态代码,例如 422 Unprocessable Entity,它告诉客户端服务器无法使用给定的参数处理请求。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...