How to create app-wide slug routing for Rails app?

There may be a way to do this with freindly_id but i think the problem with friendly id is things are scoped by model.

If I wanted truely sitewide slugging I would create a slugs table with a polymorphic relationship to all my models.

Sluggable_type and sluggable_id and then a slug field with the complete permalink/slug.

+---------------------------------------------+
| sluggable_type | sluggable_id |     slug    |
|      user      |       13     |  users/john |
+---------------------------------------------+

Now i could do do a wildcard catch all route or create the routes for all my slugs at runtime and force a route refresh when a model is updated that was under this sluggable control.

routes.rb

  get "/*segments",
               :controller => 'slugs',
               :action => 'dynamicroute'

Now in your SlugsController implement a method like

def dynamicroute
  segments = params[:segments]
  slugs.find_by_slug(segments)
  slug.sluggable_type.constantize.find(slug.sluggable_id) #retrive real record
  #some magic to handle the slugged item maybe redirect to the appropriate
  #controller or somehow call the show view for that controller
end

OR

routes.rb

begin  
  Slug.all.each do |s|
    begin
      get "#{s.slug}" => "#{s.sluggable_type.demodulize.pluralize.camelize}#show"
    rescue
    end
  end
rescue
end

If you use the 2nd approach to routing make sure you call

YOUR_APP_NAME::Application.reload_routes!

After editing any slugged record to refresh the routing table.

We’ve had similar issues and we may try our hand at gemifying this approach.

Leave a Comment