Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Rails Gravatar code and task (See related posts)

My application_helper had a basic gravatar function, but gravatar.com is best used cached.
def gravatar(email, user='')
  "<img alt=\"#{user}'s image\" src=\"/gravatars/#{MD5.new(email)}.gif\" height=\"80\" width=\"80\"/>"
end


lib/gravatar_api.rb:
require 'rc_rest'
class GravatarAPI < RCRest

  @@cache_dir = "/rails/gravatars/"
  cattr_accessor :cache_dir

  # from: http://www.gravatar.com/implement.php?#section_1_1
  # An optional "rating" parameter may follow with a value of [ G | PG | R | X ]
  # that determines the highest rating (inclusive) that will be returned.
  # see also rating guidelines: http://www.gravatar.com/rating.php
  @@acceptable_rating = "PG"
  cattr_accessor :acceptable_rating

  def wget_gravatar(md5)
    info = get_info md5
    # return true if file_expired && I decide on adding a time expiry :)
    `rm #{cache_dir}#{md5}.gif` if File.exists?("#{cache_dir}#{md5}.gif") || File.symlink?("#{cache_dir}#{md5}.gif")
    if info.success && GravatarAPI.rating_ok(acceptable_rating)
      `wget -r -O #{cache_dir}#{md5}.gif http://www.gravatar.com/avatar.php?gravatar_id=#{md5}`
      return true
    else
      `ln -s #{cache_dir}no_image.gif #{cache_dir}#{md5}.gif`
      return false
    end
  end

  def self.rating_ok(actual_rating)
    ratings = %w{ X R PG G }
    ratings.index(actual_rating) >= ratings.index(@@acceptable_rating)
  end

  class Error < RCRest::Error; end

  def initialize
  end

  def check_error(xml)
    raise Error, "unkown error" if !xml.elements['gravatar']
  end

  def make_url(md5)
    URI.parse "http://www.gravatar.com/info/md5/#{md5}"
  end

  Info = Struct.new :success, :rating, :xml
  def parse_response(xml)
    result = Info.new

    result.xml = xml
    result.success = xml.elements['gravatar/code'].text == "200"

    if result.success
      result.rating = xml.elements['gravatar/rating'].text
    end

    result
  end

  def get_info(md5)
    get md5
  end
end


lib/tasks/gravatar.rake
The intention is for "sudo rake cache_gravatars" to be a cron job
desc "wget's the gravatars for all the user emails in your database. call with RAILS_ENV=production or it defaults to development"
task :cache_gravatars => :environment do |t|
  require 'md5'
  require 'gravatar_api'
  ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
  g_api = GravatarAPI.new
  users = (User.find :all).collect {|u| u if u.email? }.compact
  users.each do |user|
    md5 = MD5.new(user.email).hexdigest
    has_g = g_api.wget_gravatar(md5)
    puts "added " + (has_g ? "file" : "symlink" ) + " for " + md5
    if has_g != user.has_gravatar? # Only update object if necessary
      user.has_gravatar = !user.has_gravatar
      user.update
    end
    #sleep(1) # you know, to play nice with gravatar.com if you have a gazillion records
  end
end


Finally, the signup code does an extra call:
def signup
  @user = User.new(params[:user])
  return unless request.post?
  begin
    g_api = GravatarAPI.new
    @user.has_gravatar = g_api.wget_gravatar( MD5.new(@user.email).hexdigest )
  rescue Exception => e
    logger.warn("unable to get gravatar info for user: " + @user.id)
    @user.has_gravatar = false
  end
  @user.save!
...


Migration used:
class Gravatar < ActiveRecord::Migration
  def self.up
    add_column :users, :has_gravatar, :boolean, :default => false
  end

  def self.down
    remove_column :users, :has_gravatar
  end
end


The deployment procedures adds a symbolic link from public/gravatars to /rails/gravatars.

You need to create an account or log in to post comments to this site.


Click here to browse all 5140 code snippets

Related Posts