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:
lang-ruby
# 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