Scope Routes/URLs By Username (like Twitter) in Your Rails Application

There are a few things that need to be taken care of before you can get this to work. The first thing (although, any of the following steps can be done in any order) to take care of involves your User model. You need to override the to_param method, so that Rails will appropriately use the username attribute rather than user_id when constructing paths.

#in app/models/user.rb
def to_param
  "#{self.username}"
end

Next we move onto routing our resources. Here it gets a little tricky because Rails is building paths for us. Remeber, you can get a list of all currently defined routes in your application by running the routes rake task

rake routes

We need to set the path_prefix option on any of our resources we want scoped by the username. For instance, in this example, I have set up a Status model and statuses_controller, whose urls shall be scoped by the username. You can apply the path_prefix to any number of other resources in your routes config file. They symbol used is arbitrary, but will be made available in the params hash, in this case params[:user_id]. You also need to exclude the show action on your users resources declaration. The reason is that, otherwise, Rails will include the controller name in the path like /users/username, which doesn’t look as clean as just /username. You then need to redefine this route explicitly (last line in the routes config shown here).

#in app/config/routes.rb
map.resources :statuses,   :path_prefix => '/:user_id'
map.resources :users,     :except => [:show]
map.user '/:username' :controller => 'users', :action => 'show'

Finally, you get to call these routes in your views or use them in your controllers. You use the same link_to, url_for methods to generate paths. When constructing the resources you have setup with the path_prefix declartion, remember you need the user model as the first argument, followed by said resource.

<%= link_to(status.title, status_path(status.user,status) %>
# or in a controller
redirect_to status_path( status.user, status )

That’s pretty much it. If anyone has another way of doing this let me know!

Yield a Block within Rails Helper Method with Multiple Content_tags Using Concat

To clean up some repetitive html coding in views, pass a block of text to a helper function which will wrap it for you the same way, each and every time. For example, I have a ‘help’ link which will toggle the display of a block of text if a link is clicked. I use this “+/- help” link throughout my application in various views. I could create a partial but this gets messy. Instead this is what I want to write in my views…

<% help do %>
  here is my help text...
<% end %>

which will render HTML similar to this…

<a href='#' 'class='help' id='help_link_123456' onclick='some_func_to_toggle_state'>+/- help</a>
<div id="help_123456">
  here is my help text...
</div>

In order to accomplish this you need to create a helper method. Assigning a unique id, just a random number, will help avoid collisions with the state of the toggled div if you use this more than once per page. Placing other HTML helper methods inside the concat() method allows multiple tags as well as rendering the block passed to the function in the appropriate place. It looks a little unwieldy, but works nicely.

# app/helpers/application_helper.rb
module ApplicationHelper
  def help(&block)
    uniqid = rand; concat( link_to_function("+/- help") do |page|
      page["help_#{uniqid}"].toggle
      page.visual_effect :highlight, "help_#{uniqid}"
    end + content_tag(:div,:class=>"help",:id=>"help_#{uniqid}", :style=>"display:none") do
      yield
    end )
  end
end