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.