Peter Marklund

Peter Marklund's Home

Mon October 13, 2008
Programming

Rails Tip: SEO Friendly URLs (Permalinks)

There are several plugins already out there that can turn the typical Rails show path of /articles/show/1 into something more search engine friendly. I decided to roll my own implementation and it turned out to be fairly easy. My solution relies on the Slugalizer library by Henrik Nyh. First, I make sure we can turn any string into something URL friendly by patching the String class:

class String
  # Convert String to something URL and filename friendly
  def to_uri(max_size = 150, separator = "-")
    no_slashes = self.gsub(%r{[/]+}, separator)
    Slugalizer.slugalize(no_slashes.swedish_sanitation, separator).truncate_to_last_word(max_size, separator)
  end

  # We need this for SEO/Google reasons sincen å should become aa and Slugalizer translates å to a.
  def swedish_sanitation
    dup = self.dup
    dup.gsub!('å', 'aa')
    dup.gsub!('Å', 'aa')
    dup.gsub!('ä', 'ae')
    dup.gsub!('Ä', 'ae')
    dup.gsub!('ö', 'oe')
    dup.gsub!('Ö', 'oe')
    dup.gsub!('é', 'e')
    dup.gsub!('É', 'e')
    dup
  end
  
  def truncate_to_last_word(length, separator = "-")
    dup = self.dup
    if dup.size > length
      truncated = dup[0..(length-1)]
      if truncated.include?(separator)
        truncated[/^(.+)#{separator}/, 1]
      else
        truncated
      end
    else
      dup
    end
  end
end

All I have to do in my ActiveRecord model then is to override the to_param method:

  def permalink
    if name.present?
      "#{id}-#{name.to_uri}"
    else
      id
    end
  end

  def to_param
    permalink
  end

ActiveRecord will automatically ignore any non-digit characters after the leading digits in an id that you pass to it, but just to be on the safe side I added a before_filter to my application controller that will convert permalinks to proper ids:

  def convert_permalink_to_id
    if params[:id].present? && params[:id] =~ /\D/
      params[:id] = params[:id][/^(\d+)/, 1]
    end
  end

Credit for parts of this code goes to my cool programmer colleagues over at Newsdesk.se.

Comments

Richard said over 6 years ago:

And in Rails 2.2 Slugalizer has become core stuff (String#parameterize). So:

Slugalizer.slugalize(no_slashes.swedish_sanitation, separator).truncate_to_last_word(max_size, separator)

becomes:

no_slashes.swedish_sanitation.parameterize.truncate_to_last_word(max_size, separator)

--------------------------------------------------------------------------------

Anon said over 6 years ago:

Where do you get the #present? method from?

--------------------------------------------------------------------------------

Anon said over 6 years ago:

I extended Object with

def present?
respond_to?(:blank?) ? (not blank?) : !self
end

amwrite?

--------------------------------------------------------------------------------

malcolm coles said over 5 years ago:

SEO friendly URLs are a bit of a myth. Search engines don't really care ... Still use them though, as they are good for humans! http://www.malcolmcoles.co.uk/blog/seo-friendly-urls-myth-and-fact/ But I'm campaining to change their names ...

--------------------------------------------------------------------------------

malcolm coles said over 5 years ago:

Hmm. That link should be:
http://www.malcolmcoles.co.uk/blog/seo-friendly-urls-myth-and-fact/

--------------------------------------------------------------------------------

avisra said over 4 years ago:

SEO friendly URLs are NOT a myth. Search terms in the slug help with keyword ranking. There is plenty of proof that this helps. Google even releases this information inside Google Webmaster Central.

--------------------------------------------------------------------------------