If you don’t know what is a sitemap, I strongly encourage you to fill this gap in knowledge first and then get back to reading.

It seems to be clear that manual updating a sitemap can turn into a horror. Hopefully we can make the Rails do the job for us.

So, what components are we going to need to build a dynamic sitemap? Well, we are going to need a separate action (or even controller), an XML view and model methods to provide us with URL data. Let’s start from creating the Sitemap controller and its index action:

$ script/generate controller Sitemap index

Above code will create the app/views/sitemap/index.html.erb file, but we need to change its extension to rxml. The reason is that we need an XML view, not an HTML view as usual. Let’s change the extension now:

$ mv index.html.erb index.rxml

To instruct Rails to send appropriate content type headers, we need to set the headers option inside the controller. We also have to disable layout rendering:

class SitemapController < ApplicationController
  def index
    @urls = ['http://lukaszwrobel.pl/', 'http://lukaszwrobel.pl/about-me']

    headers['Content-Type'] = 'application/xml'
    render :layout => false

The next thing we are going to need is an adequate XML view, located in the app/views/sitemap/index.rxml file. On the assumption that the @urls property contains list of all URLs we want to show in the sitemap, our XML view looks like this:

xml.instruct! :xml, :version => '1.0'
xml.tag! 'urlset', 'xmlns' => "http://www.sitemaps.org/schemas/sitemap/0.9" do
  @urls.each do |url|
    xml.tag! 'url' do
      xml.tag! 'loc', url

When we display the OUR_SITE_URL/sitemap page, we should see properly generated XML sitemap file:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

But the truth is that we didn’t achieve anything interesting; we still have to manually input the URL list.

The next part is application-specific. If we maintain a list of products and we want to put the URL to every product page in our sitemap, we have to get all product ids, names etc. using the find() method and build all URLs. The url_for() method could be turned into good use here. Automatically generated URLs can than be merged with the @urls property inside the Sitemap controller.

Last but not least, for some reason we may want to pretend that the sitemap is located inside a file, not a controller’s action. To achieve this effect, we need to potter with the config/routes.rb file a little. We should add the following line:

map.sitemap 'sitemap.xml', :controller => 'sitemap'

Voila! The sitemap is now available at the OUR_SITE_URL/sitemap.xml address.

comments powered by Disqus