Rails Gravatar code and task
1 2 def gravatar(email, user='') 3 "<img alt=\"#{user}'s image\" src=\"/gravatars/#{MD5.new(email)}.gif\" height=\"80\" width=\"80\"/>" 4 end
lib/gravatar_api.rb:
1 2 require 'rc_rest' 3 class GravatarAPI < RCRest 4 5 @@cache_dir = "/rails/gravatars/" 6 cattr_accessor :cache_dir 7 8 # from: http://www.gravatar.com/implement.php?#section_1_1 9 # An optional "rating" parameter may follow with a value of [ G | PG | R | X ] 10 # that determines the highest rating (inclusive) that will be returned. 11 # see also rating guidelines: http://www.gravatar.com/rating.php 12 @@acceptable_rating = "PG" 13 cattr_accessor :acceptable_rating 14 15 def wget_gravatar(md5) 16 info = get_info md5 17 # return true if file_expired && I decide on adding a time expiry :) 18 `rm #{cache_dir}#{md5}.gif` if File.exists?("#{cache_dir}#{md5}.gif") || File.symlink?("#{cache_dir}#{md5}.gif") 19 if info.success && GravatarAPI.rating_ok(acceptable_rating) 20 `wget -r -O #{cache_dir}#{md5}.gif http://www.gravatar.com/avatar.php?gravatar_id=#{md5}` 21 return true 22 else 23 `ln -s #{cache_dir}no_image.gif #{cache_dir}#{md5}.gif` 24 return false 25 end 26 end 27 28 def self.rating_ok(actual_rating) 29 ratings = %w{ X R PG G } 30 ratings.index(actual_rating) >= ratings.index(@@acceptable_rating) 31 end 32 33 class Error < RCRest::Error; end 34 35 def initialize 36 end 37 38 def check_error(xml) 39 raise Error, "unkown error" if !xml.elements['gravatar'] 40 end 41 42 def make_url(md5) 43 URI.parse "http://www.gravatar.com/info/md5/#{md5}" 44 end 45 46 Info = Struct.new :success, :rating, :xml 47 def parse_response(xml) 48 result = Info.new 49 50 result.xml = xml 51 result.success = xml.elements['gravatar/code'].text == "200" 52 53 if result.success 54 result.rating = xml.elements['gravatar/rating'].text 55 end 56 57 result 58 end 59 60 def get_info(md5) 61 get md5 62 end 63 end
lib/tasks/gravatar.rake
The intention is for "sudo rake cache_gravatars" to be a cron job
1 2 desc "wget's the gravatars for all the user emails in your database. call with RAILS_ENV=production or it defaults to development" 3 task :cache_gravatars => :environment do |t| 4 require 'md5' 5 require 'gravatar_api' 6 ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym) 7 g_api = GravatarAPI.new 8 users = (User.find :all).collect {|u| u if u.email? }.compact 9 users.each do |user| 10 md5 = MD5.new(user.email).hexdigest 11 has_g = g_api.wget_gravatar(md5) 12 puts "added " + (has_g ? "file" : "symlink" ) + " for " + md5 13 if has_g != user.has_gravatar? # Only update object if necessary 14 user.has_gravatar = !user.has_gravatar 15 user.update 16 end 17 #sleep(1) # you know, to play nice with gravatar.com if you have a gazillion records 18 end 19 end
Finally, the signup code does an extra call:
1 2 def signup 3 @user = User.new(params[:user]) 4 return unless request.post? 5 begin 6 g_api = GravatarAPI.new 7 @user.has_gravatar = g_api.wget_gravatar( MD5.new(@user.email).hexdigest ) 8 rescue Exception => e 9 logger.warn("unable to get gravatar info for user: " + @user.id) 10 @user.has_gravatar = false 11 end 12 @user.save! 13 ...
Migration used:
1 2 class Gravatar < ActiveRecord::Migration 3 def self.up 4 add_column :users, :has_gravatar, :boolean, :default => false 5 end 6 7 def self.down 8 remove_column :users, :has_gravatar 9 end 10 end
The deployment procedures adds a symbolic link from public/gravatars to /rails/gravatars.