When following RESTful routes design pattern, if you want to see data associated with a specific item, you need to provide its id. For instance, if we have a Snail model and we'd like to see information about garden snail, we'd need to know that its id is 1 in our database to get data from this endpoint:
/snails/1
This is not perfect because while it's understandable by our database that 1 stands for the garden snail entry, we humans don't find it too straightforward. Wouldn't it make our life and frontend design much easier if instead we could call:
/snails/gardenSnail?
This kind of endpoint is what we call slug or vanity url. Let's build one!
1. Controller
In our controller, we need to specify now that the attribute we will use to look for a snail is no longer id but name.
class SnailsController < ApplicationController
before_action :find_snail, only: [:show]
def show
begin
render json: @snail, status: 200
rescue StandardError => e
render json: {"error": ("#{e.message}") }, status: 400
end
end
def find_snail
@category = Category.find_by(name: params[:name])
end
end
note: It doesn't have to be a name, it can be anything you want as long as it's an attribute in the database. If you want to create a very confusing slug (e.g. to obfuscate it), then you could add slug attribute and make the to_param method return a random string e.g. by using uuid gem.
2. Routes
Now, let's overwrite the RESTful id with name:
Rails.application.routes.draw do
get '/snails/:id', to: 'snails#show', as: 'snail', param: :name
end
Or, if you are fond of using resources:
Rails.application.routes.draw do
resources :snails, param: :name, only: [:index, :show]
end

Top comments (0)