【问题标题】:Rails - routes resources duplicationRails - 路由资源重复
【发布时间】:2020-04-14 14:11:40
【问题描述】:

我在 routes.rb 文件中设置了以下路由:

Rails.application.routes.draw do
  devise_for :users

  resources :bookings do
    collection do
      get :my_bookings
    end
  end

  resources :spaces, only: [:index, :new, :create, :show] do
    resources :bookings, only: [:index, :new, :create, :show]
  end

  resources :bookings do
    resources :payments, only: :new
  end

  root to: 'pages#home'
  get 'about', to: 'pages#about'

  mount StripeEvent::Engine, at: '/stripe-webhooks'
end

我重复了resources :bookings 3 次:两次,因为我知道这是避免嵌套资源超过一个级别和另一个集合的好习惯。

当我在路由末尾添加集合部分时,rails Rails 忽略了它,而是点击了显示操作。

我阅读了Rails ignores collection route and goes with show action instead,并在最后移动了收集部分。

现在一切正常,但是路线文件很庞大,并且资源 :booking 重复了 3 次。有没有办法以更少的重复来重构这些路线?

【问题讨论】:

    标签: ruby-on-rails ruby routes


    【解决方案1】:

    如果你只专注于避免重复,你并不会真正改善路线。 DRY 很好,但在重构时它确实应该排在优先级列表的后面。相反,您希望专注于使您的路由 RESTful,shallow nesting 并在不同的上下文中处理相同的资源:

    Rails.application.routes.draw do
      devise_for :users
    
      # /bookings/my_bookings is not very RESTful as its "backwards" 
      # a better solution is /my/bookings or /user/bookings which are real nested routes
      # @see https://guides.rubyonrails.org/routing.html#singular-resources
      resource :user, only: [] do
        # this will route /user/bookings to Users::BookingsController
        resources :bookings, only: [:index], module: :users
      end
    
      resources :spaces, only: [:index, :new, :create, :show] do
        # shallow: true will prevent the member routes from being nested 
        # it will also prevent resources :payments from being nested in `/spaces/`
        resources :bookings, shallow: true do
           resources :payments, only: :new, shallow: true
        end
      end
    
      root to: 'pages#home'
      get :about, to: 'pages#about'
    
      mount StripeEvent::Engine, at: '/stripe-webhooks'
    end
    

    实际上有两种方法可以在不同的上下文中处理相同的资源。您可以将所有内容合并到同一个控制器中,并根据“父 ID”参数的存在添加代码分支,或者您可以将请求路由到不同的控制器。后者避免违反单一职责原则。

    【讨论】:

    • 我创建了一个单独的控制器:#controllers/users/bookings_controller.rb。内容:class Users::BookingsController < ApplicationController def index @bookings = current_user.bookings end end 还有视图```views/users/bookings/index.html.erb```。一切都运行良好,不确定我是否过于复杂的文件夹结构并违反了一些命名约定......
    • 完美。它一点也不复杂。
    【解决方案2】:

    您可以组合两个顶级(非嵌套)resources :bookings 块,如下所示:

    Rails.application.routes.draw do
      devise_for :users
    
      resources :bookings do
        collection do
          get :my_bookings
        end
    
        resources :payments, only: :new
      end
    
      resources :spaces, only: [:index, :new, :create, :show] do
        resources :bookings, only: [:index, :new, :create, :show]
      end
    
      root to: 'pages#home'
      get 'about', to: 'pages#about'
    
      mount StripeEvent::Engine, at: '/stripe-webhooks'
    end
    

    这应该是等效的,并且更整洁一些。不过,您将不得不保留嵌套的resources :bookings,但这没关系。并且对于/spaces/:space_id/bookings URL 结构是必需的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多