Rails Slug Routing using Param and Path
Order matters!What I wanted was a rails 7 app that can navigate to categories from the root path '/' using the slug of category. But I still want to be able to go to a scaffold's index with /icons or /instruments. A module ReservedSlugs will protect creating any categories with slugs that are being reserved by these icons, flickr_photos or whatever else. But you'll see because of my route config, going to /instruments will give me an error. It's supposed to go to instruments index, but it's looking for a category named instruments instead!
#models/concerns/reserved_slugs.rb module ReservedSlugs RESERVED_SLUGS = %w(flickr_photos categories instruments makes up icons) end # models/category.rb class Category < ApplicationRecord include ReservedSlugs validates :slug, exclusion: { in: RESERVED_SLUGS } validates(:slug, :title, presence: true) validates_uniqueness_of :slug def to_param slug end end
# config/routes.rb Rails.application.routes.draw do resources :makes get 'dashboard/index' get 'dashboard' => 'dashboard#index' resources :flickr_photos get 'categories' => 'categories#index', as: 'category_index' resources :categories, except: [:index], param: :slug, path: '/', constraints: :slug.in?(ReservedSlugs::RESERVED_SLUGS) do resources :makes end resources :icons get 'instruments' => 'categories#index', as: 'category_index' resources :instruments do resources :flickr_photos end # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. # Can be used by load balancers and uptime monitors to verify that the app is live. get "up" => "rails/health#show", as: :rails_health_check # Defines the root path route ("/") root "instruments#index" end

In routes the categories resource is sandwiched between :flickr_photos and before :instruments.
going to /instruments was giving me this error
Solution
The fix is to add the categories route definition at the end, so order matters.
You'll see the constraints: :slug.in? was my idea to fix this but it is not even needed. The first routes take presedence over the last one so I could remove this and now resources :categories looks like this:
You'll see the constraints: :slug.in? was my idea to fix this but it is not even needed. The first routes take presedence over the last one so I could remove this and now resources :categories looks like this:
# this will do the trick
Rails.application.routes.draw do
resources :makes
get 'dashboard/index'
get 'dashboard' => 'dashboard#index'
resources :flickr_photos
resources :icons
resources :instruments do
resources :flickr_photos
end
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
# Can be used by load balancers and uptime monitors to verify that the app is live.
get "up" => "rails/health#show", as: :rails_health_check
# Defines the root path route ("/")
root "instruments#index"
get 'categories' => 'categories#index', as: 'category_index'
resources :categories, except: [:index], param: :slug, path: '/' do
resources :makes
end
end