Hacking Off

20% Time All the Time

Generate Rails Sitemap From Routes

In a nutshell:

  1. add sitemap_generator to your Gemfile
  2. rake sitemap:install in your rails directory
  3. modify config/sitemap.rb to
    1. iterate over routes
    2. filter out bad routes
    3. add each iterated route to the index
  4. (optional) add other sitemaps to the sitemap index (useful if you have Jekyll or Octopress living in public/subdir).
  5. schedule updates with cron or regenerate sitemap upon deploy/push/etc.
Gemfile
1
gem 'sitemap_generator'
RAILSROOT
1
$ rake sitemap:install
RAILSROOT/config/sitemap.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SitemapGenerator::Sitemap.default_host = "http://hackingoff.com"

SitemapGenerator::Sitemap.create do
  routes = Rails.application.routes.routes.map do |route|
    {alias: route.name, path: route.path.spec.to_s, controller: route.defaults[:controller], action: route.defaults[:action]}
  end

  # Set a list of controllers you don't want to generate routes for.
  # /rails/info in particular maps to something inaccessible.
  # redirects have a nil controller. This prevents duplicate content penalties.
  banned_controllers = ["rails/info", nil]
  routes.reject! {|route| banned_controllers.include?(route[:controller])}

  # sitemap_generator includes root by default; prevent duplication
  routes.reject! {|route| route[:path] == '/'}

  routes.each {|route| add route[:path][0..-11]} # Strips off '(.:format)

  # Notice the below if you're hosting Jekyll/Octopress in a subdirectory
  # or otherwise want to index content outside of Rails' routes.
  # add_to_index '/path/sitemap.xml'

Booyah. Better living through technology. For versions of rails older than 3.2, check out http://stackoverflow.com/a/10138878/1296445 and adapt the routes assignment accordingly.

For information about automatically regenerating the sitemap and pinging search engines via cron or upon deploy, read the sitemap generator gem’s documentation. In my case, a post-receive hook for git fit the bill well enough.