ZedBee
ZedBee

Reputation: 2378

Rails Routes - Id and name with spaces replaced with hyphens

I am developing my first application in rails. I went through the Rails Routing from the Outside In documentation but unable to figure out how to setup the following route.

I have a ClientsController and the for the show action I want to display the client's first and last name with spaces replaced with hyphens, in the url.

Instead of the following

localhost:3000/clients/1

the link should be (first name : john, last name : doe)

localhost:3000/clients/1/john-doe

Upvotes: 0

Views: 405

Answers (3)

Andrew Schwartz
Andrew Schwartz

Reputation: 4657

The strategy here is to treat the name in the URL like a throw-away variable, since it's not being used as an identifier. Notice that in StackOverflow you can type any name you want, and as long as the id is correct you'll get the page you want. So we can do that too:

  1. Define the normal routes using resources :clients so you can go to /clients/1
  2. Define a another route get 'clients/:id/:name', to: 'clients#show', as: :client_name. This lets you go to /clients/1/anything-you-want and it will hit the show action in ClientsController with id: 1 and name: "anything-you-want".
  3. Define a method to generate the url-name from the user's name. For simplicity I'll assume you have defined User#url_name, but it might make more sense to define url_name(client) in a helper since it's not really relevant to the model.
  4. In your app, use client_name_path(@client.id, @client.url_name); e.g., client_name_path(1, "john-doe"). This url-helper name is defined by our choice to use as: :client_name in the route. The return value of this call should be "/clients/1/john-doe", which we have already routed to the ClientsController#show action.

So far, links in your app will have the correct URL, but a user could still type in any name in the URL and it would persist in the address bar (even though the page would be fine). If you want to go further like StackOverflow and actually change the url to the correct name you might try in ClientsController#show, to redirect_to client_name_path(@client.id, @client.url_name) if params[:name] != @client.url_name. Just be careful with that to not get yourself into an infinite loop.

Upvotes: 1

Anthony E
Anthony E

Reputation: 11235

I think you mean localhost:3000/clients/john-doe not localhost:3000/clients/1/john-doe? (The /1/ would be redundant in the latter case).

Your first option would be to define a to_param method in your User model. You would need to return a parameter starting with the id of your model:

def to_param
  [id, first_name, last_name].join("-")
end

User.find_by(last_name: "doe").to_param # => 1-john-doe

If you really don't want the ID in your user model, then consider using the Friendly ID gem: https://github.com/norman/friendly_id

I'd urge caution against using first-last as an identifier in your route, however. First, what happens if you have two users with the same first/last name (it'll happen eventually)? Second, what if your users have unusual names, such as those with spaces or apostrophes (e.g. "O'neill", etc.)? You can always URL encode such cases, but it won't look pretty.

Upvotes: 2

Alfie
Alfie

Reputation: 2784

You cannot do that out of the box in rails. But you can achieve that using friendly_id gem

Upvotes: 0

Related Questions