Currently I have a route that looks like this:
resources :posts
I want to override the 'show' action so that I can display a url like this:
posts/:id/:slug
I am currently able to do this by adding a custom match
route:
resources :posts
match 'posts/:id/:slug' => 'posts#show'
However, when I use the link_to
helper, it does not use my custom show route.
<%= link_to 'show', post %> # renders /posts/123
How can I define my show route so that I can still use the link_to
helper?
Update: As you can read in the following answers, you can override the route to the 'show' action, but it's probably more work than it's worth. It's easier to just create a custom route:
# config/routes.rb
match 'posts/:id/:slug' => 'posts#show', as: 'post_seo'
# app/views/posts/index.html.erb
<%= link_to post.title, post_seo_path(post.id, post.slug) %>
and define helper
db/migrate/add_slug_to_articles.rb
models/article.rb
Or...
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
https://github.com/norman/friendly_id
You have two routes which point to
posts#show
(you should be able to confirm this by runningrake routes
), and your link is using the wrong one.When you call
link_to('show', post)
the URL of the link is generated by callingurl_for(post)
which (eventually, after passing through several other methods on the way) callspost_path(post)
. Since the route toposts#show
that was created by your call toresources(:posts)
is namedpost
, that is the route thatpost_path
generates.You also currently have inconsistent routes for the show, update and destroy actions which will probably cause you problems later on.
You can fix this by changing your routes to the following:
Unfortunately you still can't use
link_to('show', post)
just yet, because it relies on being able to usepost.to_param
as the single argument needed to build a path to a post. Your custom route requires two arguments, anid
and aslug
. So now your link code will need to look like this:You can get around that problem by defining your own
post_path
andpost_url
helpers inapp/helpers/posts_helper.rb
:Which means we're finally able to use:
If that all seems like too much work, a common alternative is to use URLs that look more like
posts/:id-:slug
, in which case you can stick with the standard RESTful routes and just override theto_param
method in yourPost
class:You'll also need to do a little bit of work splitting up
params[:id]
into an ID and a slug before you can look up the relevant instance in your show, edit, update and destroy controller actions.