4

Stackoverflow urls are like this one:

http://stackoverflow.com/users/12345/name-of-user

It has all attributes of a true RESTful route:

:resource_name/:resource_id

But it also has a name part after a :resource_id segment. I know how to achieve it using a Non-Resourceful Routes of Rails. But is it possible to achieve the same urls using its built-in default resources :user methods?

By default the third segment is a format in Rails:

/users/:id(.:format)      users#show
4
  • 1
    FWIW, that extra string is often called a "slug". Commented May 27, 2013 at 3:15
  • Thank you. I didn't know it has it's own definition. Commented May 27, 2013 at 3:21
  • Yeah. Knowing what people usually call it will make searching for it much easier. Commented May 27, 2013 at 3:22
  • @Green, I know this is an old question , did you happen to find a way to do this with resources on your own? Commented Sep 15, 2014 at 21:29

3 Answers 3

1

I know this is an old question but it seems to still get some interests. So I'll post what I came up with.

I am not sure how far you want to be resourceful but this, with globing, works:

resources :articles do
  member do
    get '*slug', to: 'articles#show', as: 'slugged'
  end
end

This also works:

resources :articles do
  member do
    get ':slug', to: 'articles#show', as: 'slugged'
  end
end

In both case, you can then use

 <%= link_to slugged_article_path(article, article.title.parameterize) %>

in your views (you might want to define a virtual attribute in your model for the slug, instead of building it dynamically with article.title.parameterize in the view).

Note that so far, Rails will not complain if you enter anything as the slug in your browser.

I personally find the resourceful approach a bit verbose since I am only interested having pretty urls for the show actions (which are the only ones that may be seen by the regular users or the search engine bots) so I find it more simple to simply do:

resources :articles
get 'articles/:id/:slug', to: 'articles#show', as: 'slugged_article'
Sign up to request clarification or add additional context in comments.

Comments

0

You can use FriendlyId. there is a repository in Github and well documented . Ryan bates also make a very good video tutorial about it in RailsCasts

1 Comment

As mentioned in the original question you can certainly do all of this without using resources easily enough, but friendly_id doesn't address setting up the routing using resources unless there's something specific you want to refer to within.
0

Let's say you have a controller questions_controller.

In routes.rb:

get 'questions/:id/:slug', to: 'questions#show'

In questions_controller.rb:

def show
  @question = Question.find(params[:id])
  if request.path != question_path(@question)
    redirect_to @question, status: :moved_permanently
    return
  end
...
end

In question.rb:

def to_param
  "#{id}/#{name.parameterize}"
end

That's it. All generated paths will include the slug, and if try to access /questions/42, or /questions/42/incorrect-slug, you are redirected.

1 Comment

Original question, and same one I have, is how to do the same thing using resources, or if it's even possible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.