Override nested named route parameters

2019-07-18 17:48发布

问题:

Coming from the Rails docs, one can simply do this:

resources :videos, param: :identifier

But, what if I have nested resources? Here are the routes:

resources :videos
  resources :images
end

The above generate routes like:

video_images GET  /videos/:video_id/images(.:format)                  images#index

How can I override :video_id from the route? I can't seem to be able to use param in this case.

回答1:

If you want :identifier instead of :video_id you will have to code the routes manually. Which is a pain, so you should really consider why you want non-standard param values in your application.

get 'videos/:identifier/images', to: 'images#index', as: 'video_images'

Note that you'll need to do this for all CRUD routes...

get 'videos/:identifier/images/:id', :to => "videos#show", :as => "video_image"
get 'videos/:identifier/images/new', :to => "videos#new", :as => "new_video_image"
post 'videos/:identifier/images', :to => "images#create"
get 'videos/:identifier/images/:id/edit', :to => "images#edit", :as => "ed it_video_image"
put 'videos/:identifier/images/:id', :to => "images#update"
delete 'videos/:identifier/images/:id', :to => "images#destroy"


回答2:

I will try to enhance an unaccepted answer in linked question: https://stackoverflow.com/a/29138733/2405850

try to use nesting with member - it will disable default appending for parent resource id.

However that will make problems with things that probably we want to preserve like names of helpers. One way to fix this - using as (see example below).

Having similar problem I, moreover, still wanted default id for other urls (for example, default videos CRUD or where video is the only possible parent). So I finally I came up with this:

resources :videos do
  resources :snapshots
end

resources :videos, param: :imageable_id, only: [] do
  member do
    resources :images, as: 'video_images'
  end
end

resources :users, param: :imageable_id, only: [] do
  member do
    resources :images, as: 'user_images'
  end
end

The code above will generate the following routes:

    video_snapshots GET    /videos/:video_id/snapshots(.:format)           snapshots#index
                    POST   /videos/:video_id/snapshots(.:format)           snapshots#create
 new_video_snapshot GET    /videos/:video_id/snapshots/new(.:format)       snapshots#new
edit_video_snapshot GET    /videos/:video_id/snapshots/:id/edit(.:format)  snapshots#edit
     video_snapshot GET    /videos/:video_id/snapshots/:id(.:format)       snapshots#show
                    PATCH  /videos/:video_id/snapshots/:id(.:format)       snapshots#update
                    PUT    /videos/:video_id/snapshots/:id(.:format)       snapshots#update
                    DELETE /videos/:video_id/snapshots/:id(.:format)       snapshots#destroy
             videos GET    /videos(.:format)                               videos#index
                    POST   /videos(.:format)                               videos#create
          new_video GET    /videos/new(.:format)                           videos#new
         edit_video GET    /videos/:id/edit(.:format)                      videos#edit
              video GET    /videos/:id(.:format)                           videos#show
                    PATCH  /videos/:id(.:format)                           videos#update
                    PUT    /videos/:id(.:format)                           videos#update
                    DELETE /videos/:id(.:format)                           videos#destroy
       video_images GET    /videos/:imageable_id/images(.:format)          images#index
                    POST   /videos/:imageable_id/images(.:format)          images#create
    new_video_image GET    /videos/:imageable_id/images/new(.:format)      images#new
   edit_video_image GET    /videos/:imageable_id/images/:id/edit(.:format) images#edit
        video_image GET    /videos/:imageable_id/images/:id(.:format)      images#show
                    PATCH  /videos/:imageable_id/images/:id(.:format)      images#update
                    PUT    /videos/:imageable_id/images/:id(.:format)      images#update
                    DELETE /videos/:imageable_id/images/:id(.:format)      images#destroy
        user_images GET    /users/:imageable_id/images(.:format)           images#index
                    POST   /users/:imageable_id/images(.:format)           images#create
     new_user_image GET    /users/:imageable_id/images/new(.:format)       images#new
    edit_user_image GET    /users/:imageable_id/images/:id/edit(.:format)  images#edit
         user_image GET    /users/:imageable_id/images/:id(.:format)       images#show
                    PATCH  /users/:imageable_id/images/:id(.:format)       images#update
                    PUT    /users/:imageable_id/images/:id(.:format)       images#update
                    DELETE /users/:imageable_id/images/:id(.:format)       images#destroy

so for every other imageable class you will have to add another ugly construction like above but it should at least preserve other things and act as expected.