A basic sitemap generator for building a sitemap on the fly. I’d like a better way, but since it’s hosted on heroku and the map isn’t too big yet, this should work for now.

Add a route to handle building the XML

# /app/controllers/static_controller.rb
def sitemap
  xml = ::SitemapGenerator.create!('http://fixmycarin.com') do |map|
    map.add '', priority:0.9 , changefreq: :daily
    map.add '/faq', priority:0.7 , changefreq: :weekly
    map.add '/places', priority:0.7, changefreq: :weekly 
    map.add '/contact', priority:0.7, changefreq: :weekly 

    places = Place.all
    places.each{|u| map.add(place_path(u), lastmod:u.updated_at, changefreq: :weekly)}
  end
  render :xml => xml
end

Add a route to point to the above action

#/config/routes.rb
get 'sitemap.xml' => "static#sitemap"

Add a link in the robots.txt file

Sitemap: http://fixmycarin.com/sitemap.xml

Add the class that creates the XML. I put it in app/lib or app/services. This was adapted from this gist

# from: https://gist.github.com/288069
require 'builder'

class SitemapGenerator
  def initialize url
    @url = url
    yield(self) if block_given?
  end

  def add url, options = {}
    (@pages_to_visit ||= []) << options.merge(url:url)
    
  end

  def generate_sitemap
    xml_str = ""
    xml = Builder::XmlMarkup.new(:target => xml_str, :indent => 2)

    xml.instruct!
    xml.urlset(:xmlns=>'http://www.sitemaps.org/schemas/sitemap/0.9') {
      @pages_to_visit.each do |hash|
        unless @url == hash[:url]
          xml.url {
            xml.loc(@url + hash[:url])
            xml.lastmod(hash[:lastmod].utc.strftime("%Y-%m-%dT%H:%M:%S+00:00")) if hash.include? :lastmod
            xml.priority(hash[:priority]) if hash.include? :priority
            xml.changefreq(hash[:changefreq].to_s) if hash.include? :changefre
           }
        end
      end
    }

    return xml_str
  end

  # Notify popular search engines of the updated sitemap.xml
  def update_search_engines
    sitemap_uri = @url + 'sitemap.xml'
    escaped_sitemap_uri = CGI.escape(sitemap_uri)
    Rails.logger.info "Notifying Google"
    res = Net::HTTP.get_response('www.google.com', '/webmasters/tools/ping?sitemap=' + escaped_sitemap_uri)
    Rails.logger.info res.class
    Rails.logger.info "Notifying Yahoo"
    res = Net::HTTP.get_response('search.yahooapis.com', '/SiteExplorerService/V1/updateNotification?appid=SitemapWriter&url=' + escaped_sitemap_uri)
    Rails.logger.info res.class
    Rails.logger.info "Notifying Bing"
    res = Net::HTTP.get_response('www.bing.com', '/webmaster/ping.aspx?siteMap=' + escaped_sitemap_uri)
    Rails.logger.info res.class
    Rails.logger.info "Notifying Ask"
    res = Net::HTTP.get_response('submissions.ask.com', '/ping?sitemap=' + escaped_sitemap_uri)
    Rails.logger.info res.class
  end
end