问题描述
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::User
或 Api::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,它告诉客户端服务器无法使用给定的参数处理请求。