Ruby 命名空间

Ruby namespacing

我是 ruby 的新手,来自 php 背景,但有些东西不合我意。

所以,假设我在 Rails 应用程序上有一个 Ruby,我正在对 API 进行版本控制,如下所示:

app
|_controllers
  |_api
  | |_v1
  | | |_application_controller.rb
  | | |_user_controller.rb
  | |_application_controller.rb
  |_application_controller.rb

与 class 结构与

# 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::ApplicationControllerApi::ApplicationControllerApllicationController 进行扩展?

除非我指定 Api::ApplicationController,否则 < ApplicationController 会寻找它自己的命名空间吗?如果是这样,如何指定根?

当你使用

#The code in question
module Api
  module V1
    class UserController < ApplicationController
    end
  end
end

ApplicationController定义将在 Api::V1 中搜索,如果在 Api 中找不到,那么如果在根命名空间中找不到。

我同意这可能会造成混淆,这就是为什么我倾向于像这样使用绝对路径:::ApplicationController

如果我需要 Api::ApplicationController,我会写 ::Api::ApplicationController

基本上 :: 告诉 ruby 从根命名空间开始,而不是从代码所在的位置开始。


旁注

请注意Rails开发模式存在恶性案例。为了获得速度,加载了严格的最小值。然后 Rails 在需要时查找 类 定义。

但这有时会失败,例如,当您说 ::User 已经加载,然后寻找 ::Admin::User 时。 Rails 不会寻找它,它会认为 ::User 可以解决问题。

这可以在您的代码中使用 require_dependency 语句来解决。速度是有代价的:)

您应该查看指南以了解路由: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing

我觉得这个问题很像:

Rails Controller Namespace

作为短缺:

Rails 将由文件夹自动检测命名空间。所以你不需要将它附加到名称:

这个博客post解释得很好:

http://blog.makandra.com/2014/12/organizing-large-rails-projects-with-namespaces/

Let's say we have an Invoice class and each invoice can have multiple invoice items:

class Invoice < ActiveRecord::Base
  has_many :items
end

class Item < ActiveRecord::Base
  belongs_to :invoice
end

Clearly Invoice is a composition of Items and an Item cannot live without a containing Invoice. Other classes will probably interact with Invoice and not with Item. So let's get Item out of the way by nesting it into the Invoice namespace. This involves renaming the class to Invoice::Item and moving the source file to app/models/invoice/item.rb:

 class Invoice::Item < ActiveRecord::Base
   belongs_to :invoice
 end

同样适用于控制器和视图。

我宁愿建议不要在命名空间中写 ApplicationController,我建议遵循以下

注意:如果您正在构建专业的 api,那么让 Api::V1::BaseController 继承自 ActionController::Base 总是好的,尽管我正在针对您的具体情况提供解决方案

参考此 post: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 步)

然后路由将包含命名空间 routing in 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