【问题标题】:Rails 3 Routing - specifying an exact controller from within a namespaceRails 3 Routing - 从命名空间中指定一个精确的控制器
【发布时间】:2011-04-11 00:25:42
【问题描述】:

我遇到了一些我以前没有遇到过的路由命名空间问题。这实际上是我正在做的一些 gem 开发的一部分 - 但我已经修改了这个问题以适应更通用的 rails 情况。

基本上,我有一个命名空间路由,但我希望它指向一个通用(顶级)控制器。

我的控制器是PublishController,它处理许多不同类型模型的发布——它们都符合相同的接口,但可以在不同的命名空间下。我的路线如下所示:

# config/routes.rb

namespace :manage do
  resources :projects do
    get 'publish' => 'publish#create'
    get 'unpublish' => 'publish#destroy'
  end
end

问题在于这会创建以下路线:

manage_project_publish GET    /manage/projects/:project_id/publish(.:format)        {:controller=>"manage/publish", :action=>"create"}
manage_project_unpublish GET    /manage/projects/:project_id/unpublish(.:format)      {:controller=>"manage/publish", :action=>"destroy"}

这是我想要的路线,只是没有映射到正确的控制器。我已经尝试了所有我能想到的尝试并允许控制器不携带命名空间,但我很难过。

我知道我可以执行以下操作:

get 'manage/features/:feature_id/publish' => "publish#create", :as => "manage_project_publish"

产生:

manage_project_publish GET    /manage/projects/:project_id/publish(.:format)        {:controller=>"publish", :action=>"create"}

但理想情况下,我更喜欢使用嵌套声明(为了便于阅读)——如果可能的话;我开始认为不是。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 routing


    【解决方案1】:

    resource 采用可选的哈希值,您可以在其中指定控制器

    resource :projects do
    

    应该写成

    resource :projects, :controller=>:publish do 
    

    【讨论】:

      【解决方案2】:

      当您想要一个作用域路由而不是同名模块中的控制器时,请使用 scope 而不是 namespace

      【讨论】:

      • 我原本也想这样做 - 但不幸的是,由于这实际上是作为 gem 的一部分作为路由辅助方法打包的,所以我无法控制包装方法。因此,我为什么要寻找一种“突破”当前命名空间的方法。
      • 并且范围不会创建命名路由 AFAIK
      • 您可以在作用域末尾使用as: :blah 来做到这一点。
      • 如果我可以再次投票,我会的。这在上下文中是非常稀缺的知识。
      【解决方案3】:

      如果我理解你的正确,你想要这个:

      scope :manage do
        resources :projects, :only => [] do
          get 'publish' => 'publish#create'
          get 'unpublish' => 'publish#destroy'
        end
      end
      

      制作这些路线:

      project_publish     GET    /projects/:project_id/publish(.:format)    {:action=>"create", :controller=>"publish"}
      project_unpublish   GET    /projects/:project_id/unpublish(.:format)  {:action=>"destroy", :controller=>"publish"}
      

      我是否正确理解了您的需求?如果是这样,这就是 Ryan 的解释。

      【讨论】:

      • 你说得对,scope 非常适合这种情况,您希望 URL 有范围,但控制器不在 URL 中。
      • 谢谢威廉,我可以发誓我当时尝试过这个 - 但我必须挖掘项目并看看。
      【解决方案4】:

      我想你想要的是这样的:

      namespace :manage, module: nil do
        resources :projects do
          get 'publish' => 'publish#create'
          get 'unpublish' => 'publish#destroy'
        end
      end
      

      这确实会根据需要创建命名路由(manage_projects...),但仍会调用控制器::Publish

      【讨论】:

        【解决方案5】:

        这有点晚了,但对于仍在为此苦苦挣扎的人,您可以在控制器名称中添加一个前导斜杠,以将其从任何现有命名空间中拉出。

        concern :lockable do
          resource :locks, only: [] do
            post "lock" => "/locks#create"
            post "unlock" => "/locks#destroy"
          end
        end
        

        现在,如果您在任何地方(无论是否命名空间)都包含该关注点,您将始终点击 LocksController。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-07
          • 2014-05-19
          • 1970-01-01
          • 2012-08-20
          • 2017-01-18
          • 2023-03-11
          • 2012-07-08
          • 1970-01-01
          相关资源
          最近更新 更多