Creating a Sitemap Automagically for Rails App

Sitemaps help in making sure that your app is properly indexed, so it would help to automatically have them generated (and updated) so a search engine knows when a new web page is created, or an old one updated.  Luckily, there’s a gem, SitemapGenerator that makes it extremely easy to do this.

All you have to do  in Rails 3 is:

  1. add: gem ‘sitemap_generator’ to your gemfile
  2. run “rake sitemap:install” which creates config/sitemap.rb
  3. customize sitemap.rb

A simple example (where “Content” is a model name)

SitemapGenerator::Sitemap.default_host = "http://www.example.com"
SitemapGenerator::Sitemap.create do
  add '/contact_us'
  Content.find_each do |content|
    add content_path(content), :lastmod => content.updated_at
  end
end

4. run “rake sitemap:refresh”

5.  change your robots.txt file (if you have one) to include this line (so search engines can find it easy):

Sitemap: http://www.example.com/sitemap_index.xml.gz

6.  if you’re using Heroku, like me, you’ll have to take extra steps, as in this example, to write the files to somewhere else since Heroku is read-only.

7.  Also, if you’re using Heroku, you may want to use Heroku Scheduler to automatically refresh the sitemap by adding this task:

$ rake sitemap:refresh

8.  Lastly, to make sure Google indexes your site better, you’ll want to enter the path to your sitemap in a Google Webmaster Tools account for your site – the same as the address in step 5, unless you are using Heroku or another read-only system (and the sitemap is stored on another domain).  In this case, since Google Webmaster tools only accepts url’s from your domain (for the sitemap location), you’ll have to re-route them to the external location.  To do that you can make a simple controller like this example from Bill Rowell or you can use the rack-rewite gem.

Getting ActiveAdmin to Work on Heroku

The ActiveAdmin gem was working for me in development, but not in production.  The reason, I found, was because not all of the assets used by ActiveAdmin were getting precompiled by Heroku.  To solve the issue, I used the code by Ryan Long’s answer on Stack Overflow (in production.rb).

# Precompile additional assets. Defaults to [application.js, application.css, non-JS/CSS]
config.assets.precompile += ['active_admin.css', 'active_admin/print.css', 'active_admin.js']

Sign Out Wasn’t Working with Devise for Me

Devise’s Sign Out wasn’t working for me. I’ve seen other solutions, but they didn’t worked for me. However, I found an answer that worked for me on Devise’s wiki.

Previously, I used this link:

<%= link_to "Logout", destroy_user_session_path, method: :delete %>

However, that wasn’t working, so I changed (in config/initializers/devise.rb in ):

config.sign_out_via = :delete

to:

config.sign_out_via = :get

and revised the link to (removed “method: :delete”):

<%= link_to "Logout", destroy_user_session_path %>

Error: mysql2 gem compiled for wrong mysql client library

I was receiving this error after switching to the MySQL2. It turns out the reason is because I needed to update my MySQL connector.

To do that I
(1) went to: http://www.mysql.com/downloads/connector/
(2) I selected Connector/C (libmysql)
(3) I downloaded the Windows (x86, 32-bit), ZIP Archive no-install
(4) I placed it in my ruby/bin directory, which for me was in: C:\RailsInstaller\Ruby1.9.3\bin

Error: C:/Dev/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require’: 193: %1 is not a valid Win32 application

I was receiving this error which was preventing me fom running my Rails server or any other commands locally:

C:/Dev/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require’: 193: %1 is not a valid Win32 application.   – C:/Dev/Ruby193/lib/ruby/1.9.1/i386-mingw32/digest/sha1.so (LoadError)

It started after I implemented a web hook, which conflicted with a local application.  I found out by after finding this post:

https://github.com/oneclick/rubyinstaller/issues/102

In the case of the poster, an app called FRAPS was causing the issue.  I don’t have that program, but after closing a bunch of apps from Windows’ Task Manager, it was working again.

Making the Asset Pipeline Less Verbose

I was getting a little overwhelmed by the amount of messages regarding each asset in my development logs, so I wanted to make my logs less verbose.  It was making it more challenging to find the real actions and queries I was trying to analyze.

I found the answer in this post on Stack Overflow.

For some people, adding the initializer code worked, but for me, I went with adding:

config.assets.debug = false

in config/enviroments/development.rb 

and that was sufficient for me.  I’m using Rails 3.1 and I noticed different settings people used in 3.2, so it may also be different if you use 3.2.

Showing Line Breaks

I needed to show line breaks when displaying a text area field that users populated without having them add html.  For example, my app allowed for people to enter text which could span multiple paragraphs.  I didn’t want people to have to enter html, but I wanted it to show line breaks based on if user put line breaks (carriage returns) when they entered the paragraphs.

I found an answer on Stackoverflow.  When you want to display the text field, use code like this:

<%= h(obj.description).gsub(/\n/, ‘<br/>’).html_safe %>

where “obj” = your model, and “description” = your text field.

I also think that simple_format will work, as described here.

Allowing HTML Tags in Form Fields

I wanted to allow my users to be able to include html tags in things they posted.  Originally, I was thinking that this was done as an option to the form field, but it actually is in the view where you display the user content.

In my case, I have this in the form:

<%= f.text_area :content %>

and where you want to display it, just add “.html_safe”, for example:

<%= article.content.html_safe %>

Triggering jQuery on Page Load

I had some jQuery on a page that changes with a change to a field in a form, like so:

<%= tax.select(:state , Order::STATES ,{:prompt => ‘Select State’}, :id => “state”,:onchange => “render_sales_tax()”) %>

The issue was that when a user received an error with the form and the user populated the field again (ie :state), then when the view was rendered again (ie format.html { render :action=>”new” }  ), the  jQuery would not be triggered again because the field was already populated when rendered again (so no onChange event).

To fix this, I had to add this line above the jQuery function in the <script> section of the page:

window.onload = render_sales_tax();

This way the jQuery triggered and then onChange it would update again (if necessary).