【问题标题】:Ruby namespacingRuby 命名空间
【发布时间】: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::ApplicationControllerApi::ApplicationControllerApllicationController 来进行扩展?

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

【问题讨论】:

    标签: ruby-on-rails ruby namespaces


    【解决方案1】:

    当你使用

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

    ApplicationControllerdefinition 将在 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
    

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

    【讨论】:

      猜你喜欢
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      • 2013-06-22
      • 2015-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多