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)