Rails在范围和资源内部的顶级路由

时间:2018-04-05 12:02:11

标签: ruby-on-rails routing

在我的Rails应用程序中,我有以下控制器:

/controllers/journeys_controller.rb
/controllers/policies/journeys_controller.rb
/controllers/policies/drivers/journeys_controller.rb
/controllers/policies/vehicles/journeys_controller.rb

他们的代码如下:

class JourneysController < ApplicationController

    def custom_1; end

    def custom_2; end

end

module Policies
    class JourneysController < ApplicationController

        def index; end

        def show; end

    end
end

module Policies
    module Drivers
        class JourneysController < ApplicationController

            def index; end

            def show; end

        end
    end
end

module Policies
    module Vehicles
        class JourneysController < ApplicationController

            def index; end

            def show; end

        end
    end
end

因此,您可以看到我有方法列出并显示政策,司机和车辆的行程。然后我在顶级旅程控制器上有自定义方法。

到目前为止我的路线是:

resources :policies, only: %i[index show] do
  scope module: :policies do
    resources :journeys, only: %i[index show] do
      get 'custom_1' => 'journeys#custom_1'
      get 'custom_2' => 'journeys#custom_2'
    end
    scope module: :drivers do
      resources :journeys, only: %i[index show] do
        get 'custom_1' => 'journeys#custom_1'
        get 'custom_2' => 'journeys#custom_2'
      end
    end
    scope module: :vehicles do
      resources :journeys, only: %i[index show] do
        get 'custom_1' => 'journeys#custom_1'
        get 'custom_2' => 'journeys#custom_2'
      end
    end
  end
end

然而,这些自定义路线并未指向顶级控制器:

enter image description here

enter image description here

他们实际上指的是他们的父范围(这是有道理的)。但在我的情况下,我想将这些自定义方法指向顶层。如何使这些路由指向不同的控制器,但保持它们嵌套,以便URL保持原状。

2 个答案:

答案 0 :(得分:0)

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

resource : journeys do
# code
end

将写为

resource : journeys, controller :journeys, module: nil do
 # code
end

在模块中,你必须指出nil

答案 1 :(得分:0)

首先,这只是一个简单的坏主意,因为你不应该嵌套超过one level deep。如果您仍然打算这样做,您将声明路由如下:

Rails.application.routes.draw do
  resources :policies, only: %i[index show] do
    # declare anything "top-level" here
    get :top_level_custom_action

    scope module: :policies do
      resources :journeys, only: %i[index show] do
        get :custom_1
        get :custom_2
      end

      resources :drivers, only: [] do
        resources :journeys, module: :drivers, only: %i[index show] do
          get :custom_1
          get :custom_2
        end
      end

      resources :vehicles, only: [] do
        resources :journeys, module: :vehicles, only: %i[index show] do
          get :custom_1
          get :custom_2
        end
      end
    end
  end

  # if you want to create a seperate unested route then declare it in its own 
  # resources block
  resources :journeys, only: [:show, :edit, :update, :destroy]
end

但是嵌套深度并为嵌套资源提供show路由是一种反模式,因为每个资源都有唯一的id,并且可以在没有父资源的情况下直接访问。例如,GET policies/1/drivers/2/journeys将指向与GET /drivers/2/journeys完全相同的资源。

有限嵌套的更好解决方案是:

Rails.application.routes.draw do
  resources :journeys, only: [:index, :show, :edit, :update, :destroy]

  resources :policies, only: %i[index show] do
    resources :journeys, module: :policies, only: %i[index show] do
      get :custom_1
      get :custom_2
    end
  end

  resources :drivers do
    resources :journeys, scope: :drivers, only: %i[index]
  end

  resources :vehicles do
    resources :journeys, scope: :vehicles, only: %i[index]
  end
end