18

So I'm looking for a solution that would help me achieve the following with Rails resource:

/admin/articles/:slug/edit

as opposed to

/admin/articles/:id/edit

I'm looking for Rails resource routes and not the other kinds of routes.

Just wanted to know if it was possible. If so, how?

Flip
  • 6,233
  • 7
  • 46
  • 75
sidegeeks
  • 1,021
  • 3
  • 12
  • 17
  • I think this is a copy of http://stackoverflow.com/questions/482636/fetching-records-with-slug-instead-of-id – sajinmp Jun 25 '15 at 20:23
  • 1
    Consider a gem like friendly_id if you're building a production site, or at least check the readme to get an idea of the edge cases. https://github.com/norman/friendly_id – thebenedict Jun 25 '15 at 20:31

2 Answers2

36
# config/routes.rb
resources :articles, param: :slug

In the terminal:

$ rake routes
...
article GET    /articles/:slug(.:format)      articles#show
...
Thomas Klemm
  • 10,678
  • 1
  • 51
  • 54
  • Are you sure that the param option is in Rails 3? –  Dec 09 '15 at 14:25
  • Should be, but at least it is available in Rails 4+. – Thomas Klemm Dec 09 '15 at 18:44
  • 1
    Is this a "one-step" solution? i.e., once you add `param: :slug` your `link_to article.name, article`, for instance, will generate a link to a slug, and that slug will be recognized? Either the answer is no or I'm doing something else wrong :) – Jonathan Tuzman Jan 23 '19 at 23:04
  • @JonathanTuzman If the path then looks correct (e.g. `/articles/my-great-article`), you'll have to the controller to handle the slug param, e.g. `@article = Article.find_by!(slug: params[:slug])` – Thomas Klemm Feb 11 '19 at 13:51
  • 1
    @JonathanTuzman you need to add another method to the model to make sure, the changed parameter gets used with `link_to article`: `def to_param slug end` will make sure, the slug is used instead of the id. More can be read here: https://guides.rubyonrails.org/routing.html#overriding-named-route-parameters – orly Nov 17 '20 at 13:29
17

The :id parameter in the routing is simply a placeholder and can be anything, from a numeric identifier to a slug.

You just need to pass the proper value

article_path(id: @article.slug)

and fetch the article using the appropriate method

Article.find_by!(slug: params[:id])

If you prefer, you can also override the to_param for the Article model to return the slug, so that you can use

article_path(@article)

and automatically the slug will be assigned to the :id parameter.

Simone Carletti
  • 173,507
  • 49
  • 363
  • 364