【问题标题】:double namespaced routing issues with fetchfetch 的双重命名空间路由问题
【发布时间】:2023-03-25 19:30:02
【问题描述】:

你好>我正在创建一个包含书籍和用户的 Javascript SPA/Rails Api。我在路由中使用命名空间,以及每个模型的序列化程序。我不确定为什么在尝试为用户执行 post fetch 请求时出现此错误。我不确定我的书是否会遇到同样的问题。 Belo 你可以看到我的控制器顶部的每个控制器都有 Api::V1....等。然后我在我的路线中有我的命名空间路线。我的 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)
                })
            })
    }

【问题讨论】:

    标签: javascript ruby-on-rails routes rails-api javascript-namespaces


    【解决方案1】:

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

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

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

    然而,这段代码还有很多问题,因为它充斥着糟糕的 api 设计决策 - 潜在的 nil 错误(通过使用 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,它告诉客户端服务器无法处理具有给定参数的请求。

    【讨论】:

      猜你喜欢
      • 2012-01-25
      • 2017-12-13
      • 1970-01-01
      • 1970-01-01
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 2011-03-09
      • 2017-02-19
      相关资源
      最近更新 更多