Wednesday, October 14, 2009

Podcast: Introduction to Ruby

In eSpace's first podcast, I had a chance to give a 10-minute introduction to Ruby.



Check it out.






Tuesday, July 21, 2009

eSpacians @ RubyKaigi 2009

Take a look at Ehab and OldMoe of eSpace delivering a talk about eSpace's Ruby contributions at RubyKaigi 2009 in Japan, the Ruby homeland.



Note: don't get too bored of Ehab talking in Japanese at first, OldMoe is coming up in English with core stuff :)





Sunday, June 7, 2009

Facebook Connect: Avoid race conditions with FB.ensureInit

I've been playing with Facebook Connect for a while now. Actually, the JavaScript client library is such a relief. It enables the API consumer to distribute the overhead of Facebook API calls on all the clients, hence dramatically boost the application performance.

However, IMHO, there is a single major issue with The Facebook JavaScript client library. To make it clear, let's take a quick look on the typical steps to use the library. There are two main steps:

1. initializing the library


var fbApiKey = "your_api_key_here";
FB.init(fbApiKey, "/xd_receiver.htm");


2. Making the desired API call

var fbClient = new FB.ApiClient(fbApiKey);
fbClient.users_getInfo(fbUserId, ['name', 'hometown_location', 'birthday'], showUserInfo);


The exact previous code snippet seems okay. Actually, it runs perfect in most cases. However, the previous code snippet would 'sometimes' cause an error and wouldn't run. What kills me is that the error is not clear: "Can't get base domain property when api key is not set" !!

After digging it up for a while, I found out the cause of the 'inconsistent' problem. The initialization call "FB.init" is asynchronous. The initialization process starts and the code continues on running. The error occurs in the cases where the API call happens to run before the asynchronous call is done (i.e. FB is not fully initialized). As confusing as the problem could get, the solution was pretty simple; instead of making the API call directly, attach your call to the callback of the great "FB.ensureInit" function:

FB.ensureInit(function(){
var fbClient = new FB.ApiClient(fbApiKey);
fbClient.users_getInfo(fbUserId, ['name', 'hometown_location', 'birthday'], showUserInfo);
});


What really drives me crazy is that, the API calls that requires complete initialization are known. Why wouldn't the library internally handle this burden ??!! Why wouldn't the implementation of all those call internally block until FB is fully initialized ??!! That's a question whose answer I would really like to know someday.


Thursday, May 28, 2009

Facebook Connect: IE problem with Feed/Share dialogs

I've been playing with Facebook Connect for a while, integrating it with a web application I am working on. One of the pages was demanded to show the feed dialog that lets the user publish a news feed entry on his Facebook Wall. The way to do it seemed pretty simple; given the Facebook feed template id, A single JavaScript call was needed:


FB.ensureInit( function(){
FB.Connect.showFeedDialog(templateId, templateData, targets, feedBody, 2, FB.RequireConnect.doNotRequire, null);
});


That worked just fine with Firefox. However, when trying it on IE, it 'occasionally' causes the page to crash during loading. No explicit JavaScript error was shown, the page just crashes.

After digging it up for a long time, I failed to find out the exact reason that causes the problem. However, with a little help from OldMoe, I succeeded in defining the exact scenario of the crash, that previously seemed inconsistent. What showFeedDialog does is that, it inserts an iframe in the page, makes a post request and loads the feed dialog inside it. The crash generates only when the iframe loads before the original page completes loading. Obviously, disregarding the exact reason of the scenario, the solution was to ensure DOM loaded before calling showFeedDialog:


document.observe("dom:loaded", function() {
FB.ensureInit( function(){
FB.Connect.showFeedDialog(templateId, templateData, targets, feedBody, 2, FB.RequireConnect.doNotRequire, null);
});
});