gpt4 book ai didi

ruby-on-rails - Rails 中 Controller 的嵌套命名空间

转载 作者:数据小太阳 更新时间:2023-10-29 07:00:58 27 4
gpt4 key购买 nike

我重构了我的 Rails 应用程序,我为每个子资源创建了一个 Controller ,这是相应的命名空间。

api/v1/app/controller/manager.rb
api/v1/app/controller/manager/user.rb
api/v1/app/controller/manager/controller.rb
api/v1/app/controller/admin.rb
api/v1/app/controller/user.rb
api/v1/app/controller/controller.rb

manager命名空间下的用户资源的类定义是这样的

class Api::V1::Manager::UserController < ApplicationController

此 Controller 可通过 routes.rb 访问:

 resources :manager , only: [:show ] do
resources :user, only: [:index], controller: 'manager/user'
end

产生

/api/v1/manager/:manager_id/user(.:format)       api/v1/manager/manager#index {:format=>"json"}

模型都在

app/models/manager.rb
app/models/user.rb

当我现在想访问 api/v1/app/controller/manager/user.rb Controller 或 api/v1 中的 Manager 模型时/app/controller/manager.rb 例如

class Api::V1::ManagerController < ApplicationController
def index
Manager.find(...)
end
end

class Api::V1::Manager::UserController < ApplicationController
def index
Manager.find(...)
end
end

我得到这些错误

{"error":"uninitialized constant Api::V1::Manager::UserController::Manager"}%   
{"error":"uninitialized constant Api::V1::Manager::Manager"}%

调用由正确的 Controller 处理:

Processing by Api::V1::Manager::UserController#index as JSON

解决方案是在调用中使用双冒号前缀

`::Manager.find(...)`.

我可以正常使用所有其他模型 Admin.find(...)Controller.first。只有 Manager.find(..) 不工作。

将命名空间重命名为 ManagerResource 仍然会产生相同的错误消息。

我希望能够将 Controller 分组在不同的命名空间下,并且仍然以相同的方式访问所有模型,这怎么可能?

更新

创建

api/v1/app/controller/api/v1/foo/customer_controller.rb
api/v1/app/controller/api/v1/manager_customer_controller.rb

启动服务器 (webrick) 后,所有端点都正常工作。添加 Manager.first - 到任何 Controller - 或更改使用 Manager... 的文件中的某些内容会返回这些错误

`uninitialized constant Api::V1::Foo::UserController::Manager` 
`uninitialized constant Api::V1::ManagerUserController::Manager`
`uninitialized constant Api::V1::*any_controller*::Manager`

重启服务器解决了这个问题。

我可以使用 Controller.first 或任何其他模型,例如api/v1/app/controller/controller.rb。服务器响应良好。

就像@Andrey Deineko 指出的那样,我现在明白模块和类名应该不同了。

我不明白的是,当我在与模型名称不同的命名空间下减去 Controller 时,为什么这些错误只发生在特定模型上?

更新二

我删除了所有与管理器相关的 namespace 和 Controller 。所以我回到了原来的预 Controller 优化状态。

此错误仅发生在 Manger 模型中。在控制台中 Manager.class 在任何情况下都显示 Class。但是在 Controller 中会发生这种情况:

module Api
module V1
class Manager < Api::ApiBaseController
def index
puts User.class #=> class
puts Manager.class #=> module
puts ::Manager.class #=> class
puts Controller.class #=> class
...
end
end
end
end


class Api::V1::Manager < Api::ApiBaseController
def index
puts User.class #=> class
puts Manager.class #=> {"error":"uninitialized constant Api::V1::ManagerController::Manager"}
puts ::Manager.class
puts Controller.class
...
end
end

当我更改顺序时,::Manager 首先一切正常,然后类也匹配

 class Api::V1::Manager < Api::ApiBaseController
def index
puts User.class #=> class
::puts Manager.class #=> class
puts Manager.class #=> class
puts Controller.class #=> class
...
end
end

命名空间 Api::V1::... 适用于所有其他 Controller 。

最佳答案

原因很简单,答案在于Ruby的常量解析机制。

基本上,拥有同名的模块和类是非常糟糕的主意。

但是如果您确实需要为模块和类使用相同的名称,请确保正确引用它们中的每一个。

意思是,如果您不想更改命名,那么使用 :: 引用 Manager 类是您唯一的解决方案

Rails 在开发和生产模式下为自动/预加载类添加了一些魔法,因此您可能会在不同模式下面临不同的问题。

您可能需要通读 this official guide关于在 Rails 中加载常量。

关于ruby-on-rails - Rails 中 Controller 的嵌套命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39430030/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com