How to implement "short" nested vanity urls in rails?
I understand how to create a vanity URL in Rails in order to translate
http://mysite.com/forum/1
into http://mysite.com/some-forum-name
But I'd like to take it a step further and get the following working (if it is possible at all):
Instead of:
http://mysite.com/forum/1/board/99/thread/321
I'd like in the first step to get to something like this: http://mysite.com/1/99/321
and ultimately have it like http://mysite.com/some-forum-name/some-board-name/this-is-the-thread-subject
.
Is th开发者_JAVA技巧is possible?
To have this work "nicely" with the Rails URL helpers you have to override to_param
in your model:
def to_param
permalink
end
Where permalink
is generated by perhaps a before_save
before_save :set_permalink
def set_permalink
self.permalink = title.parameterize
end
The reason you create a permalink is because, eventually, maybe, potentially, you'll have a title that is not URL friendly. That is where parameterize
comes in.
Now, as for finding those posts based on what permalink
is you can either go the easy route or the hard route.
Easy route
Define to_param
slightly differently:
def to_param
id.to_s + permalink
end
Continue using Forum.find(params[:id])
where params[:id]
would be something such as 1-my-awesome-forum
. Why does this still work? Well, Rails will call to_i
on the argument passed to find
, and calling to_i
on that string will return simply 1
.
Hard route
Leave to_param
the same. Resort to using find_by_permalink
in your controllers, using params[:id]
which is passed in form the routes:
Model.find_by_permalink(params[:id])
Now for the fun part
Now you want to take the resource out of the URL. Well, it's a Sisyphean approach. Sure you could stop using the routing helpers Ruby on Rails provides such as map.resources
and define them using map.connect
but is it really worth that much gain? What "special super powers" does it grant you? None, I'm afraid.
But still if you wanted to do that, here's a great place to start from:
get ':forum_id/:board_id/:topic_id', :to => "topics#show", :as => "forum_board_topic"
Take a look at the Rails Routing from the Outside In guide.
maybe try something like
map.my_thread ':forum_id/:board_od/:thread_id.:format', :controller => 'threads', :action => 'show'
And then in your controller have
@forum = Forum.find(params[:forum_id])
@board = @forum.find(params[:board_id])
@thread = @board.find(params[:thread_id])
Notice that you can have that model_id be anything (the name in this case)
In your view, you can use
<%= link_to my_thread_path(@forum, @board, @thread) %>
I hope this helps
精彩评论