Rails 3使用命名空间进行路由

5
尝试访问以下URL时,出现404错误页面

dev.mydomain.com/api

然而,我的routes.rb文件中提到了这个路由确实存在:

routes.rb

constraints :subdomain => 'dev' do
  root :to => 'developers/main#index', :as => :developers
  namespace 'api', :as => :developers_api do
    root :to => 'developers/apidoc/main#index'
  end
end

rake routes

         developers   /(.:format)      {:subdomain=>"dev", :controller=>"developers/main", :action=>"index"}
developers_api_root   /api(.:format)   {:subdomain=>"dev", :controller=>"api/developers/apidoc/main", :action=>"index"}

controller

/app/controllers/developers/apidoc/main_controller.rb

class Developers::Apidoc::MainController < Developers::BaseController
  def index
  end
end

日志

[router]: GET dev.mydomain.com/api dyno=web.1 queue=0 wait=0ms service=14ms status=404 bytes=0
[web.1]: Started GET "/api"
[web.1]: ActionController::RoutingError (uninitialized constant Api::Developers)
3个回答

5
我猜问题出在你的路由指向了 api/developers/apidoc/main,但是你的类只有 Developers::Apidoc::MainController。你应该要么不用 api 命名空间来定义路由,要么就把控制器的命名空间加上 Api,变成 Api::Developers::Apidoc::MainController

3

还要记住的另一个重要因素是路由命名空间需要与其对应的目录路径保持一致。如果做错了,也会导致出现如下错误:

Routing Error

uninitialized constant Api::Developers

在我的情况下,我的路由结构如下所示:
namespace "api" do
  namespace "developers" do
    ...
  end
end

文件夹/目录结构应该是 app/controllers/api/developers/


1

TL;DRscope替换namespace

给定以下文件夹结构

 Rails.root
  |
  +-- app/
  |    |
  |    +-- controllers/
  |         |
  |         +-- jobs_controller.rb
  +-- config/
       |
       +-- routes.rb

routes.rb 中的以下代码片段会出现错误:ActionController::RoutingError: uninitialized constant Api:
namespace :api do
  namespace :v1 do
    resources :jobs
  end
end

while the following works:

scope :api do
  scope :v1 do
    resources :jobs 
  end
end

原因在Rails Routing from the Outside In中简要提到:

命名空间范围将自动添加:as以及:module:path前缀。

实际上,命名空间只是一个包装了一堆预定义选项的作用域。

# File actionpack/lib/action_dispatch/routing/mapper.rb, line 871
def namespace(path, options = {})
  path = path.to_s

  defaults = {
    module:         path,
    path:           options.fetch(:path, path),
    as:             options.fetch(:as, path),
    shallow_path:   options.fetch(:path, path),
    shallow_prefix: options.fetch(:as, path)
  }

  scope(defaults.merge!(options)) { yield }
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接