Ruby 命名空间
Posted
技术标签:
【中文标题】Ruby 命名空间【英文标题】:Ruby namespacing 【发布时间】:2015-07-07 08:25:09 【问题描述】:我是 ruby 的新手,来自 php 背景,但我没有点击。
所以,假设我有一个 Ruby on Rails 应用程序,并且我正在像这样对我的 API 进行版本控制:
app
|_controllers
|_api
| |_v1
| | |_application_controller.rb
| | |_user_controller.rb
| |_application_controller.rb
|_application_controller.rb
同类结构同
# Versioned API V1 app controller
module Api
module V1
class ApplicationController
end
end
end
# Versioned API app controller
module Api
class ApplicationController
end
end
# Root app controller
class ApplicationController
end
#The code in question
module Api
module V1
class UserController < ApplicationController
end
end
end
所以问题是,ruby 是否会寻找 Api::V1::ApplicationController
、Api::ApplicationController
或 ApllicationController
来进行扩展?
除非我指定Api::ApplicationController
,否则< ApplicationController
是否会查找它自己的命名空间?如果是这样,我如何指定根?
【问题讨论】:
【参考方案1】:当你使用
#The code in question
module Api
module V1
class UserController < ApplicationController
end
end
end
ApplicationController
definition 将在 Api::V1
中搜索,如果在 Api
中未找到,则在根命名空间中未找到。
我同意这可能会造成混淆,这就是我倾向于使用绝对路径的原因:::ApplicationController
如果我需要Api::ApplicationController
,我会写::Api::ApplicationController
基本上,::
告诉 ruby 从根命名空间开始,而不是从代码所在的位置开始。
旁注
请注意,Rails 开发模式中存在恶性案例。为了获得速度,加载了严格的最小值。然后 Rails 在需要时查找类定义。
但这有时会失败的大例子,当你说::User
已经加载,然后寻找::Admin::User
。 Rails 不会寻找它,它会认为 ::User
可以解决问题。
这可以在您的代码中使用require_dependency
语句来解决。速度是有代价的:)
【讨论】:
cool :) 最令人困惑的是当您遇到像我的旁注中描述的问题时 有趣,我认为你的旁注解决了我遇到的问题here @dax 读起来很酷 :) 由于这种延迟加载,我经历了很多啊哈和错误的时刻【参考方案2】:我宁愿建议不要在命名空间中写ApplicationController
,我建议遵循以下
注意:如果您正在构建专业 api,最好让 Api::V1::BaseController
继承自 ActionController::Base
,尽管我正在为您的具体情况提供解决方案
参考这篇文章:Implementing Rails APIs like a professional
1) 在 app/controllers/application_controller.rb 中以通常的方式定义应用控制器为
class ApplicationController < ActionController::Base
end
2) 在 app/controllers/api/v1/base_controller.rb 中定义基本 api 控制器,即 Api::V1::BaseController,它将继承自 ApplicationController
(您的情况),如
class Api::V1::BaseController < ApplicationController
end
3) 在 app/controllers/api/v1/users_controller.rb 中定义您的 api 控制器,如 Api::V1::UsersController
,它将继承自 Api::V1::BaseController
class Api::V1::UsersController < Api::V1::BaseController
end
4) 添加所有后续控制器,例如Api::V1::UsersController
(步骤 3)
那么路由会在config/routes.rb中包含命名空间路由
namespace :api do
namespace :v1 do
resources :users do
#user routes goes here
end
# any new resource routing goes here
# resources :new_resource do
# end
end
end
【讨论】:
尽管这并没有直接回答我的问题,但它为我提供了更广泛的 API 选择设计。谢谢。【参考方案3】:您应该查看指南以了解路由: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
我认为这个问题非常类似于:
Rails Controller Namespace
作为短缺:
Rails 将通过文件夹自动检测命名空间。所以你不需要将它附加到名称中:
这篇博文解释得很好:
http://blog.makandra.com/2014/12/organizing-large-rails-projects-with-namespaces/
假设我们有一个 Invoice 类,每张发票可以有多个 发票项目:
class Invoice < ActiveRecord::Base has_many :items end class Item < ActiveRecord::Base belongs_to :invoice end
显然发票是物品的组合,物品不能生存 没有包含发票。其他课程可能会 与 Invoice 而不是 Item 交互。所以让我们把 Item 从 通过将其嵌套到 Invoice 命名空间中。这涉及重命名 类到 Invoice::Item 并将源文件移动到 app/models/invoice/item.rb:
class Invoice::Item < ActiveRecord::Base belongs_to :invoice end
同样适用于控制器和视图。
【讨论】:
以上是关于Ruby 命名空间的主要内容,如果未能解决你的问题,请参考以下文章
ruby 从命名空间#ruby #autoload自动加载一个类