My app have products, categories and subcategries. I have an admin interface at the url /dash to edit these details. I tried to set the urls like this :

  • Products create, update, destroy and index under the url /dash/products
  • Products show under /products/porduct-code
  • Categories show under /category-name
  • Categories edit list under /dash/editcategories pointing to action editcategories
  • Subcategories show under category-name/subcategory-name
  • Edit is also under category like above
  • Category and subcategory create,update, delete and index all under /dash

When I try to fix one thing the other one breaks. My whole routes file have become a mess. Tried to fix them and things won't work. Here's my routes file :

Rails.application.routes.draw do

    # Pages
    root 'pages#home'
    get 'terms' => 'pages#termsandconditions'
    get 'delivery-charges' => 'pages#deliverycharges'
    get 'search' => 'pages#search'
    get 'deals' => 'pages#alldeals'
    get 'contact', to: 'pages#contact'
    post 'contact', to: 'pages#contactscreate'
    get 'dealslist' => 'pages#dealslist'

    get 'cart' => 'carts#cart'

    get 'rate' => 'districtrates#rate'
    get 'deliverycharges' => 'districtrates#deliverycharges'
    get 'pricecalc' => 'pages#pricecalc'

    # Devise routes

    # Others
    resources :users
    resources :brands
    resources :orders

    get 'dash/subcategorylist' => 'products#subcategorylist'
    get 'dash'  =>  'dash#index'

    get '/products/:id', to: 'pages#product'

    scope '/dash' do
        resources :districtrates, as: 'deliveryrates'
        resources :slides
        resources :images
        resources :colorqtys
        resources :products
        get 'imagelist' => 'images#imagelist'
        get 'slidelist' => 'slides#slidelist'
        get 'update_deliveryrates' => 'districtrates#update_deliveryrates'
        get 'adminlogs' => 'logs#adminlogs'
    end

    get '/:id', to: 'categories#show'

    scope '/dash' do
        get 'editcategories' => 'categories#edit_categories'
    end

    scope '/:id' do
        get '/:id', to: 'subcategories#show'
    end

    resources :categories, path: '/dash/category' do
        get 'editsubcategories' => 'subcategories#edit_subcategories'
    end

    get 'dash/category/new' => 'categories#new'
    post 'dash/categories' => 'categories#create'
    delete 'dash/category/:id' => 'categories#destroy'
    patch 'dash/category/:id' => 'categories#update'

    get 'dash/subcategory/new' => 'subcategories#new'
    post 'dash/subcategories' => 'subcategories#create'
    delete 'dash/subcategory/:id' => 'subcategories#destroy'
    patch 'dash/subcategory/:id' => 'subcategories#update'

    get 'dash/colors' => 'colors#index'

    post 'dash/saveimages' => 'images#saveimages'
    post 'dash/savecolorqtys' => 'colorqtys#savecolorqtys'
end

Please help me fix the conflict issues and cleanup my routes file. Also please give me a good guide to understand Rails routes.

1

There are 1 answers

5
max On BEST ANSWER

REST über alles:

Much of the the cruft in your routes file could be cleaned up by just sticking the rails REST conventions. This should also improve the consistency of your application. I believe that in many cases your are compromising the design of your application just to get short urls.

Putting many routes in the '/' "namespace" such as '/about', '/faq' etc works ok for small sites or if you are building an app which primarily deals with a single type of resource (like a Todo app). But it leads to a really weak design when you have many types of resources and fair share of complexity.

Putting each of your resources into its own little box (/users, /pets) makes nice RESTful interfaces and reduces complexity and the risk of routing ambiguities and conflicts.

Also you should use snake_case for readability when naming your resources:

resources :districtrates # bad
resources :district_rates # better

Lets get down and dirty with the refactoring:

get 'contact', to: 'pages#contact'
post 'contact', to: 'pages#contactscreate'

Mounting a few "static" routes inside a PagesController and creating routes "manually" is fine. But this really smells since Contract is actually something that can be modeled more restfully.

Create a ContactsController and change the route definition to:

resources :contacts, only: [:new, :create]
# GET /contacts/new
# POST /contacts

If you absolutely must have a /contact path:

get 'contact', to: 'contacts#new'
# But don't create that POST route! 

Other candidates for the same treatment are dealslist, deliverycharges.

The admin interface:

I would argue that you should either fully embrace "on page editing" (using the standard controllers, routes and views) or have an admin namespace with its own controllers and views.

So you would change your route definition to use the Dash namespace.

namespace :dash
  resources :slides
  resources :images
  resources :products
  # ...

  get 'imagelist' => 'images#imagelist' # BAD. Use images#index instead
  get 'slidelist' => 'slides#slidelist' # BAD. Use slides#index instead
end

This would route to Dash::ImagesController. Use concerns (mixins) as a method of cross-cutting duplication.

Categories and subcategories can be routed with nesting instead.

namespace :dash
  resources :categories do
    resources :categories, as: 'sub_categories', controller: 'dash/categories'
  end
end

Addition:

The public categories:

resources :categories, only: [:show] do
  resources :categories, 
            as: 'sub_categories', 
            controller: 'categories',
            only: [:show]
end