Taming the Gravatar
The service Gravatar seems to be a great service in theory: anyone who registers a picture with an email address there can have this picture associated with oneself in all applications that support Gravatar. This defies the need to having to upload a profile picture for every application being used.
With so many things that work in theory, Gravatar has had and is having some serious issues. Their servers dont quite work as well as expected. This results in pages trying to render a Gravatar image stalling and becoming irresponsive.
Since an early stage, Opinion had Gravatar support. What worked quite well in the beginning became now a hassle with pages taking forever to load. However, it does not have to be like that.
The Solution
Instead of requesting the images while rendering the page, we now request the images after the whole page has loaded via javascript. Let’s have a look at how this can be done:
Before we were having a simple image tag that would get the correct url from a helper who would look like this:
http://www.gravatar.com/avatar.php?gravatar_id=#{Digest::MD5.hexdigest(email)}&size=40&default=http%3A%2F%2F#{@request.host + @request.port_string}/images/no-gravatar.jpg
(pretty straight forward and the way it was supposed to be implemented by Gravatar – it tries to get the right picture for the MD5 of the email address provided. If it can’t find a gravatar it points us back to the default picture we define)
Now, we decide to put that default picture as background image of the future gravatar image space.
We’re just rendering hidden tags for each gravatar with the MD5 Hash of the user’s email (so we can recreate the appropriate links later ourselves once the page’s rendering is done).
they can look like:
<address class="gravatar" style="display:none"><%= Digest::MD5.hexdigest(comment.user.email) %></address>
Now we need to define a javascript method that would replace the content of an element with the correct Gravatar and one that will iterate through all potential Gravatar images:
var Gravatar = {
replaceElement: function(element) {
Element.replace(element, "<img src=\"http://www.gravatar.com/avatar.php?gravatar_id=" + element.innerHTML + "&size=40\" alt=\"\" />")
},
replaceAll: function() {
$$('address.gravatar').each(function(e){
Gravatar.replaceElement(e);
});
}
}
Finally, we just need to register our replacing js goodness to be executed after load:
Event.observe(window, 'load', function() { setTimeout(Gravatar.replaceAll, 50) } );
So ideally this will now result in the page being loaded, usable and Gravatars (for those that can be found) popping in with a short delay, covering the default user image.
Could I ask why it is necessary to use Gravitar in the first place?
I can think of a few: 1) Bandwidth 2) Disk space 3) Pages load faster when images are on a different server
I don’t think the first two are an issue unless your very very stingy with your hosting budget :)
I guess another reason would be that Gravitar provides an interface to manage the avator. But we’re rails developers and can easily knock together interfaces. And Gravitar might be an inconvenience to users.
Anyway, interested to hear your reasoning (and other peoples) as to why they use Gravitar
DebraH: I guess it’s because no-one wants to maintain an avatar on each blog / web service they participate in. It’s useful from both a user & developer perspective.
Saves time at both ends.
I ran into this issue some time back and I think someone else has done a caching solution which I was going to use on my Beast forum.
I personally happen to think that a decoupling approach when combined with a local cache would work best. I haven’t looked into Gravatar api to see if it supports “new” notifications, but I was thinking of implementing something like this:
check local cache, render if found
check with Gravatar server to see if user has changed their avatar since we cached it.
Do the asynchronous load via js if you have to hit Gravatar (not found OR user changed their gravatar)
In any case, the actual hit is going to be when there is an actual need to get the picture. Otherwise it is just a handshake and a “how-do-you-do” as it were :)
I am not surprised that Gravatar is so gawd-awfully slow. Everyone who uses the service just does the email->hash bit in the view or equivalent right before render time.
It’s a good idea, but they need to architect it a little better I think.
DebraH: The main advantage of using it is that you have a picture of anyone with an email address that once uploaded it on Gravatar associated with that person. I find it tedious to have to upload yet another 40×40, 60×60, 80×80, etc. in random maximum file sizes on various sites. For an application like a forum, it may have been a better solution to host the picture on the server or offer a hybrid solution. But for several small apps, e.g. commenting on a blog, the Gravatar idea is conceptually strong.
Amr: caching is a good idea. As far as I know, Gravatar does not support “new” notifications (maybe one day?).