Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kivanio/592300 to your computer and use it in GitHub Desktop.
Save kivanio/592300 to your computer and use it in GitHub Desktop.

Building a Facebook application with Rails and hosting it in Heroku

Introduction

Facebook has given a big step in simplicity with its Graph API and the creation of the Open Graph protocol, now more than ever it's easier to read and write data from and to the socalled social graph.

You could turn your webpage into a fully-featured Facebook-like page, just like if you were inside Facebook, you can give your users the ability to sign in with their Facebook credentials, customize your users' experience with parameters taken from their Facebook profiles, you could add a Like button to every object in your page as images, songs, articles, etc., tell your users which friends of theirs have liked your content, and a lot of things more, oh, I forgot to mention something, all of this with total ease. Yes, I know you could do it with Facebook Connect, but I said "with ease".

Ok, let's get started with the fun.

A brief explanation of the Facebook application architecture

Well sorry if I didn't jump to the actual funny part, but we really need to know the first things first, it'll save us a lot of time in the long run. I swear.

A Facebook application is actually two applications: A container application and a web application.

When we create a Facebook application in the Facebook site what we are actually creating is the container of our web app.

Let's think of our web application like if it were a painting, Facebook itself would be the stand and the container would be the canvas, now let's call the container a Canvas Application.

As you can see they both are actually two different things:

  • The stand and the canvas are hosted in Facebook
  • Our web application, which is not different than any other application we've made before, is not hosted in any Facebook server; we must store it in our own server or a hosting service.

For both of them to look like if they were only one application you have to associate them and once we do so our Canvas Application and our web app will begin to interact with each other.

Well, all of this let us with a process of three phases:

  • Creation
  • Association
  • Configuration

Actually, the association is part of the configuration, but I like to think of the process this way to keep things separate.

##Creation

####Facebook Canvas Application

This is the easiest part, you just have to go to the Facebook Developer site and setup a new application.

screenshot of the form

Input whatever application name you want in the Application Name field, like "My Facebook App", then agree the terms and click the Create Application button, after passing the Security Check you'll be presented with the Basic Information of you brand new application.

Cool, we've created our Canvas Application, now we'd need to associate it with an existing web app.

####Web application For the moment, we'll assume we already have a web application we'd like to associate with Facebook and we'll assume we are hosting it in http://my\_facebook\_app.heroku.com/

###Association

NOTE: In case you closed the previous window you can access all your applications in the My Applications page. Click the application we just created and click the Edit Settings button.

Now, click the Facebook Integration button in the settings page.

screenshot of the settings page

I'd like you to pay attention to the Canvas section, here we'll find all the settings we need to associate our existing web app with our Canvas Application.

  • Canvas Page

    By the way, sometimes you'll have to struggle to find an available name, it's like when you want to buy a .com domain, sometimes the one you want have been already bought by another person, it's unavailable, it's something like that.

  • Canvas URL

Now, when our users browses http://apps.facebook.com/my\_facebook\_app/, Facebook will show them our Canvas Application (an HTML page) which contains an IFrame (inline frame) that in turn shows http://my\_facebook\_app.heroku.com/. This kind of applications are called IFrame Canvas Applications.

   Canvas application                    Web application
      in Facebook                      in our own servers
+----------------------+       -->   +--------------------+
| Facebook chrome      |     /       |       hello!       |
|  +-----------+ <-    |   /         |                    |
|  |   hello!  |    \==|===          |                    |
|  |           |       |             |                    |
|  |   Canvas  |    /==|===          |                    |
|  +-----------+ <-    |   \         |                    |
|                      |     \       |                    |
+----------------------+       -->   +--------------------+
ToDo: make an infograhic

Fig1. An IFrame Canvas application is actually an IFrame surrounded by the Facebook chrome. The IFrame points to our web app URL.

Let's try it with our new application.

Without any fear, change the Canvas URL to http://www.heroku.com/, now open the Canvas URL in your browser. What do you see? Yes, the Heroku site, this is why it looks like your web application is inside Facebook.

####Canvas Type

  • FBML (Facebook Markup Language) Canvas Applications
  • IFrame Canvas Applications

As of today, {the date}, Facebook still allow us to create FBML Canvas Applications but they will be deprecated by the end of 2010. Click here to see the announcement.

###Configuration

Now it's time edit all the other settings to customize your application: description, logo, icon, etc. It's a very straight-forward phase, so I won't touch it here.

###The interaction between Canvas Applications, web applications and Facebook

Facebook has several mechanisms to let our web applications interact with the data of its social graph, more precisely, with the data of the users of our application, among these mechanism are:

  • Graph API - A powerful yet simple RESTful API
  • XFBML - It enables you to incorporate FBML into your websites and IFrame Canvas Applications.

Every time you want an user authorizes your application and every time you want to access your users data you'll be using the Graph API in one way or other.

Here's a diagram of how Facebook applications interact with the Graph API and XFBML.

1.User request http://apps.facebook.com/my_facebook_app
2.Facebook returns HTML code with the Facebook chrome and the IFrame
3.The IFrame request the Canvas URL to our server
4a.Our web app make a request to the Graph API (say the name of the current user)
4b.Our web app contains XFBML (a Login and a Like button)
5a.The Graph API respond with the users data in JSON/XML
5a. Facebook responds with the HTML to show the Login and Like buttons
6.Our app builds an HTML response to show the name of the current user and it is shown in the IFrame

                               1  
+----------------------+ ==============> +-----------+   
| Facebook chrome      |                 |           |  
|  +-----------+       |       2         |    FB     | ----  
|  |   hello!  |       | <============== |           |    |  
|  |           |       |                 |           |    |  
|  |   Canvas  |       |                 +-----------+    |  
|  +--+----+---+       |                           ^      |  
|     ^    |           |                           |      |  
+-----|----|-----------+                           |      |  
      |    |______________                         | 4    | 5  
      |________________    \                       |      |  
              6         \    \  3                  |      |  
                          \    \                   |      |  
                            \    \                 |      |  
                             |    `--->  +-----------+    |      
                             |           |           |    |  
                              \          |    Our    |    |  
                                `------- |   server  | <--'  
                                         +-----------+  
ToDo: make an infographic

If our application requests the Graph API via Javascript the communication would be directly with the Facebook servers.

1.Our application contains the following Javascript code:

<script>
      FB.api('/me', function(response) {
          alert(response["name"]);
      });
</script>

It's fired by the user with a button.

2.Facebook returns the response in JSON and its parsed by the callback function and it alerts with the name of the current user.

+----------------------+     
| Facebook chrome      |              +-----------+  
|  +-----------+       |    1         |           | 
|  |   hello!  | ------|----------->  |    FB     | 
|  |           |       |              |           | 
|  |   Canvas  | <-----|------------  |           | 
|  +-----------+       |    2         +-----------+                           
|                      |                             
+----------------------+ 
ToDo: make an infographic

Well, It would seem it wasn't a brief explanation but believe me, it really was.

The Facebook's Graph API

The Graph API enables you to read and write objects and connections in the Facebook social graph. It's so easy to use and it's very clean. If you want to fully understand how does the API actually works you have to know about the RESTful architecture, although it isn't completely necessary, I'd really recommend you to research about it.

The main concept to take into account is object, we have to think of every single thing in Facebook as objects: photos, events, comments, friends, tags, groups, etc. and we must know that every object in Facebook has an unique identifier, an ID.

Ok, let's query the Graph API with our browser. Click the following link to see the information of the Miles Davis page.

http://graph.facebook.com/57796847423

Now you should be seeing the response in JSON format. Among other things you will see the following information:

{
   "id": "57796847423",
   "name": "Miles Davis",
   "picture": "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs170.ash2/41611_57796847423_9040_s.jpg",
   "link": "http://www.facebook.com/MilesDavis",
   "category": "Musicians",
   "username": "MilesDavis",
   "genre": "Jazz",
   "bio": ...
   "fan_count": 363730
}

Now, we're going to query the API passing the username as parameter:

http://graph.facebook.com/MilesDavis

We get the same response, maybe there are new fans between calls but the structure is the same.

As I said earlier, that is a page, and the Graph API exposes certain public and private information of the page, In the Graph API reference > Page we will find the access points to such information, Facebooks calls them Connections.

The reference says we can access a connection called posts, let's try it:

http://graph.facebook.com/MilesDavis/posts

Right now I see something like this:

{
   "data": [
      {
         "id": "57796847423_126368887412272",
         "from": {
            "name": "Miles Davis",
            "category": "Musicians",
            "id": "57796847423"
         },
         "message": "Drummer Lenny White on Bitches Brew",
         ...
}

It's an array of Post objects, and the Graph API reference > Post page say there's a connection called Comments and that I can access them with the following URL:

http://graph.facebook.com/57796847423_126368887412272/comments/

Cool, we are seeing the comments of the post with ID=57796847423_126368887412272.

This is basically how the Graph API works, if you want to know more about it please go to the Graph API overview page.

Well, so far, we've been accessing public information, if we want to access private information we won't be able to do it this way, Facebook only allow us to access private information if we have a Facebook application and such application must be explicitly authorized to access such information.

Who authorizes our application? neither Facebook nor the FCC but the USERS, nobody else, and they are the only ones with the power to deauthorize it.

###Authentication

Facebook uses the OAuth 2.0 protocol for authentication and authorization.

Authentications means "It's me, and here's my proof"  
Authorization means "Now that you know who I am, would you let me do this or that?"  

The Facebook Authentication page explains the authentication process very well, but I'll try to summarize the process with a simple graphic:

1.Register your application to get an app ID and secret

2.https://graph.facebook.com/oauth/authorize? client_id=app_id& redirect_url=http://localhost:3000/oauth_callback

3.If the user authorizes your application, we redirect the user back to the redirect URI you specified http://localhost:3000/oauth_redirect?code=the\_code

4.Exchange the code for an oauth access token in the following URL https://graph.facebook.com/oauth/access_token? client_id=...& redirect_uri=http://localhost:3000/oauth_callback client_secret=...& code=...

5.Facebook will request the callback url with the access token http://localhost:3000/oauth_callback?access_token=3gergve5gesrdsgs

6.Store it in a DB, cookie or whereever you want, it must be used to make requests on behalf of the user.

+----------------------+     2
| Facebook chrome      |------------> +-----------+
|  +-----------+       |     3        |           |
|  |           | <-----|------------  |    FB     |
|  |           |       |    4         |           |
|  |   Canvas  | ------|------------> |           |
|  +-----^-----+       |    5         +-----+-----+
|        |-------------|-------------------/                          
+----------------------+ 
ToDo: make an infographic

Ok, now our application has been authenticated and the user has authorized it, a question raises:

What kind of information would my application access? 

The answer is:

Only the general information: email, name, etc.

This happens when we don't specify what kind of permissions we're asking for, so Facebook sets the default permissions.

Here is how we ask the user for extended permissions:

https://graph.facebook.com/oauth/authorize?
    client_id=...&
    redirect_uri=http://www.example.com/callback&
    scope=user_photos,user_videos,publish_stream

Once we get the access token our application will be able to access all the photos, videos and even write to the users's wall.

That was basically how authentication and authorization works in Facebook.

Now we have all we need to start creating real Facebook applications and the most important part, make them in Ruby.

Ruby and Facebook (The status of gems and plugins)

I've found that most of the existing gems and Rails plugins are still using Facebook Connect and the Old REST API instead of the new Graph API and that some of them doesn't work with Ruby 1.9 and/or Rails 3.

The gems we are going to use in this tutorial are proven to work with Ruby 1.9.x and Rails 3.0.0, I'd like to share with you as well the gems I tested in the process of creation of this tutorial:

Making a simple Facebook application

The fun part has finally arrived, we're about to make a simple Facebook application, how simple will our aplication be? Very simple, it will only show a list of links to interesting articles, to be exact, it'll show only two links, a Login button and some Like buttons, well, I said it'd be simple, isn't it?

I'll assume you're using Ruby 1.9.x. and that you have at least Git 1.6.x installed. To see a guide to install Git in different platforms, please click here.

If you are using any other version of Ruby I'd suggest you to install Ruby 1.9.x with RVM. If you're going to use RVM (Ruby Version Manager) you won't need to prefix the following commands with sudo (Unix-like OSs only).

Installing the needed gems.

If you don't already do so, I do really recommend you to use Bundler, it's the default gem dependency manager in Rails 3 and you'll fall in love with it as soon as you use it, well, at least I did.

$ sudo gem install bundler

We need to host our web application somewhere, let's do it the easy and fast way, let's use Heroku. We'll need to install the Heroku command-line tool, a gem that will allow us to create and deploy Heroku applications with ease.

$ sudo gem install heroku

Of course, you'll need to sign-up for a Heroku account and then configure the command-line tool, it's really a very simple process, click here to see the full instructions to do so.

What other gems are we going to use?

  • Sinatra, a DSL for quickly creating web applications in Ruby.

Installing gems with Bundler

its workflow is very simple:

$ bundle init
Writing new Gemfile to ~/simplest_fb_app/Gemfile

Take into account that the gem is called Bundler while the command-line utility is called bundle

Edit the Gemfile with your preferred text editor to let it look like this:

source :gemcutter

gem 'sinatra', '1.0'

Now we need to tell Bundler to check if we're missing the gems our application depends on, if so, tell it to install them:

$ bundle check
The following gems are missing
...

$ bundle install

If you want to know the advantages of using Bundler please check this Yehuda Katz' post out

We are all set up, let's get started!

The first step will be to create a Canvas application in Facebook, I'll name it Faceboku but you can name it whatever you want to.

These would be our application settings:

Site URL = http://faceboku.heroku.com
Canvas Page => http://apps.facebook.com/faceboku/ (instead of faceboku you must use a different one)
Canvas URL  = http://localhost:4567 (the standard port used by Sinatra applications)
Canvas Type = IFrame

If you don't see the Canvas Type option, don't worry, there's a possibility Facebook has got rid of it by the time you're reading this.

We're using http://localhost:4567 because that way we'll be able to test our Facebook application before we deploy it to Heroku.

What's next? our Sinatra application

Create a directory called simplest_fb_app wherever you want in your system, I'll do it in my home directory:

$ mkdir ~/simplest_fb_app

then create the following files and directories on it:

  • faceboku.rb (you may use the name of your canvas application)
  • config.ru
  • views/ (folder)
  • views/layout.erb
  • views/index.erb

I'll let these files look like:

faceboku.rb

require 'sinatra'

#Here you have to put your own Application ID and Secret
APP_ID = '153304591365687'
APP_SECRET = '7a7663099ccb62f180d985ba1252a3e2'

get '/' do
    @articles = []
    @articles << {:title => 'Deploying Rack-based apps in Heroku', 
				  :link => 'http://docs.heroku.com/rack/'}
    @articles << {:title => 'Learn Ruby in twenty minutes', 
                  :link => 'http://www.ruby-lang.org/en/documentation/quickstart/'}
    erb :index
end

config.ru like this:

require 'faceboku' #this is to load faceboku.rb

run Sinatra::Application

views/layout.erb

<!DOCTYPE HTML>
<html xmlns:fb="http://www.facebook.com/2008/fbml">
	<head>
		<title>Faceboku</title>
		<style>
			body { font-family: Arial; font-size: 20px ;}
			a { text-decoration: none; color: #333; }
			.article { font-size: 1.2em; }
			.like_app { font-size: 0.8em }
		</style>
	</head>
	<body>
		<%= yield %>
		<div id="fb-root"></div>
		<script>
			window.fbAsyncInit = function() {

				FB.init({
					appId: '<%=APP_ID%>',
					status: true,
					cookie: true,
			        xfbml: true
				});
			};

			(function() {
			  var e = document.createElement('script');
			  e.type = 'text/javascript';
			  e.src = document.location.protocol +
			    '//connect.facebook.net/en_US/all.js';
			  e.async = true;
			  document.getElementById('fb-root').appendChild(e);
			}());
		</script>

	</body>
</html>

views/index.erb

<fb:login-button autologoutlink="true"></fb:login-button>
<h3>Welcome to my list of interesting articles</h3>

<table>
	<% @articles.each do |article| %>
	<tr>
		<td class='article'>- <a href='javascript:void(0);'><%=article[:title]%></a></td>
		<td><fb:like href="<%=article[:link]%>" layout="button_count" show_faces="false" /></td>
	</tr>
	<% end %>
</table>

<hr />
<p><span class='like_app'>Do you like this application?</span></p>
<p><fb:like /></p>

Wow, what an amazing application!, let's run it and browse it!

$ ruby faceboku.rb

Open your browser and point it to http://localhost:4567.

This is an easy application, it let your users to login with their Facebook credentials, it let them like your links and the application itself.

This is a Facebook application, which means we can see it in action in the Facebook site, let's try it, browse the following URL http://apps.facebook.com/faceboku.

And there it is, our super application right on Facebook.

Ok, but we can't serve our application from our local machine all the time, we need a server must always be up and running, nothing simpler than Heroku, it'll be a 4 steps process, let's do it:

Assuming we are in our application directory we'll need to turn it into a git one:

$ git init

Add all the files and directories to source control:

$ git add .

Commit them to your local repository:

$ git commit -m "First version of my facebook application"

Deploy to Heroku:

$ git push heroku master

Done! Our application has been deployed to Heroku, wouldn't you like to see it right away? simple:

$ heroku open

Cool, it's right there, but wait, our Canvas application is still pointing to our local machine, we now want it to point to Heroku, let's change our Canvas URL:

Canvas URL  = http://faceboku.heroku.com

Now let's browse to our application http://apps.facebook.com/faceboku and that's it!

Download application

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment