Search code examples
ruby-on-railsruby-on-rails-4routesrails-routing

How correctly use :path_names in rails routes?


I'm writing rails application and I need to change some of URL pathes of my application. But I don't want to broke my tests and make changes in view, js or controllers...

Here is my routes:

  resources :posts, path: 'news' do
    member do
      get  'edit/page/:page', as: :edit,    action: :edit
      post '/approve',        as: :approve, action: :approve
      post '/reject',         as: :reject,  action: :reject
    end

    collection do
      get :my
      get :shared_with_me
      get :filtered
    end
  end

As you see I found a way to change domain.com/posts to domain.com/news in all website's pathes.

Now I need do change this list of pathes:

  • from domain.com/news to domain.com/news/all (get posts#index)
  • from domain.com/news/12 to domain.com/news/preview/12 (get posts#show)
  • from domain.com/news/new to domain.com/news/request (get posts#new)

I'm trying to change this pathes using :path_names, but it doesn't working...

Here is updated routes:

  resources :posts, path: 'news', path_names: {index: 'all', show: 'preview', new: 'request'} do
    member do
      get  'edit/page/:page', as: :edit,    action: :edit
      post '/approve',        as: :approve, action: :approve
      post '/reject',         as: :reject,  action: :reject
    end

    collection do
      get :my
      get :shared_with_me
      get :filtered
    end
  end

When I made this changes and runs rake routes - only GET news/request appears..

But why I don't see GET news/all and GET news/:id/review ?

Please, help me to fix it. Thanks!


Solution

  • You can specify the controller to use for a resource instead of using the path hack:

    resources :news, controller: 'posts' do
    
    end
    

    When it comes to the rest of you question maybe you should learn the hows and why's of the RESTful defaults instead.

    Using /news/all is pretty idiosyncratic - in REST its implied if a path describes a resource than the "root" should display all items.

    get 'edit/page/:page'
    

    Is just plain weird. If page is a nested resource of news you would declare it like so:

    resources :news, controller: 'posts' do
       resources :pages
       # or
       resource :page
    end
    

    You also should not be using the POST verb to approve / reject a story. POST implies that you are creating a resource. Instead you might want to do something like:

    resources :news, controller: 'posts' do
       member do
         patch :approve
         patch :reject
       end
    end
    

    Yes this will break you tests - waah waah. However building bad applications just to avoid changing existing code / tests is not a viable long term approach.