Rafael Magaña

This article was contributed by Rafael Magaña

Web developer, currently working as freelance Ruby developer
(Twitter: @rafmagana // Github: rafmagana)

Building a Facebook Application With Ruby

Last Updated: 07 October 2013

facebook tutorial

Table of Contents

Facebook has removed the Facebook Cloud Integration service. No new applications can be created through this service. Existing applications will continue to operate.

With Facebook’s Graph API and the creation of the Open Graph protocol, it is now easier then ever before to read and write data from and to the “social graph”. Here’s a few of the possibilities:

  • 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 and customize their experience with parameters taken from their Facebook profiles.
  • You could add a Like button to every object in your page such as images, songs, articles, etc., and tell your users which friends of theirs have liked your content.

In this article I’ll show you how to get started by making a very simple, but functional Facebook app and deploying it to Heroku.

Sample code for the demo Sinatra application is available on GitHub.

Facebook application architecture

First things first, you need to understand some of the underlying architecture of a Facebook app. It’ll save you a lot of time in the long run. I mean it.

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

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

  • Ones that use the Facebook APIs to add features such as Like and Share buttons to your own website at, say, www.yourcompany.com. This is called Facebook for Websites.

  • Apps that “live” on Facebook. These are the apps you add to your profile and use from within Facebook.com. Those are called Canvas Applications.

In this article, I’m going to focus exclusively on showing you how to build the latter kind, the Canvas app.

A Canvas app is actually made up of two different parts: A container that’s defined on Facebook.com, and an external web app that connects to the container, supplying the specific logic, behavior and views you define.

When you initially create a Facebook application by setting up its Canvas Page, what you are actually creating is the container of your web app. To complete the Canvas analogy, think of the external web application as if it were a painting. Facebook itself would then be the stand and the container would be the canvas.

In summary, you Facebook Canvas app will be made of:

  • The stand and the canvas, hosted on Facebook.
  • Your web application, which is not different than any other application you’ve made before, is not hosted on any Facebook server; you’re going to host it on Heroku.

As far as your customers know, it will look like a single application. To get these components to work together properly it involves 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.

Create Application

As you can see, you can select Yes, I would like free web hosting provided by Heroku, but don’t check it, we’ll host the app manually.

Input whatever application name you want in the App Name field, like “My Application”, then agree the terms and click Continue, after passing the Security Check you’ll be presented with the Basic Information of your brand new application.

Basic Information!

Cool, you’ve just created your Canvas Application, now you’d need to associate it with an existing web app.

Web application

For the moment, let’s assume you already have a web application you’d like to associate with Facebook and let’s assume you are hosting it in http://my.herokuapp.com/

Association

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

I’d like you to pay attention to the Website with Facebook Login and App on Facebook sections, here you’ll find all the settings you need to associate your existing web app with your Canvas Application.

  • Site URL - URL for your website, Facebook will only redirect to this URL (important for OAuth)
  • Canvas Page - It’s an unique access point for your application, for instance, http://apps.facebook.com/my_facebook_app/.
  • Canvas URL - Facebook will pull content from this URL and put it in an iframe (more on that later), for instance, http://my.herokuapp.com/canvas/ (the trailing slash is mandatory).

Now, when your users browse http://apps.facebook.com/my_facebook_app/, the flow would be:

  • Facebook will show them our Canvas Application (an HTML page) which contains an IFrame (inline frame)
  • Such IFrame will in turn show http://my.herokuapp.com/canvas/

These kind of applications are called IFrame Canvas Applications.

Application in Canvas

An IFrame Canvas Application is actually an IFrame surrounded by the Facebook chrome (header), this IFrame points to your application’s Canvas URL or Secure Canvas URL.

Let’s try something.

Without any fear, change the Canvas URL to be http://www.heroku.com/, now open your Canvas Page (https://apps.facebook.com/your_namespace) in your browser. What do you see? Yes, the Heroku site, this is why it looks like your web application is inside Facebook when it is not.

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 two mechanisms to let your web applications interact with the data of its social graph, more precisely, with the data of the users of your applications:

  • Graph API - A powerful yet simple RESTful API
  • XFBML - eXtended Facebook Markup Language

When your application wants to retrieve information from your users you’ll use the Graph API in one way or other, so in this article I’m going to focus on Graph API since it’s a more modern way to interact with the data than XFBML.

Here’s a diagram of how Facebook applications interact with the Graph API

  1. User requests http://apps.facebook.com/my_facebook_app
  2. Facebook returns HTML code with the Facebook chrome and the IFrame
  3. The IFrame requests the Canvas URL to your server
  4. Your web asks for the current user’s name to the Graph API
  5. Facebook responds with the data in JSON format
  6. Your app builds an HTML response to show the name of the current user and it is shown in the IFrame

Graph API interaction

If your application requests the Graph API via Javascript, the communication would be directly with the Facebook servers. Here’s an example:

Here’s a code snippet in Javascript to retrieve the name:

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

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

Call Graph API with JS

The Facebook Graph API

The Graph API enables you to read and write objects and connections in the Facebook social graph. It’s quite easy to use, and sticks very closely to RESTful architecture, which you might already be familiar with.

To understand the API, 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 see the response in JSON, most likely something that looks like this:

{
  "id": "57796847423",
  "name": "Miles Davis",
  "link": "http://www.facebook.com/MilesDavis",
  "category": "Musicians",
  "username": "MilesDavis",
  "genre": "Jazz",
  "bio": "...",
  "likes": 1338242,
  ...
}

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

http://graph.facebook.com/MilesDavis

We should get the same response.

The Graph API exposes certain public and private information of the page. By consulting the Graph API reference > Page can learn about additional access points to find different types of information (look under the Connections header).

Once of these connections is 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 Mils Davis’ Post objects, and the Graph API reference > Post page says there’s also connection called Comments and that I can access with the following URL:

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

Cool, we are fetching the comments of the post using its ID, which is 57796847423_126368887412272.

This is basically how the Graph API works. To learn more please go to the Graph API overview page.

So far we’ve been accessing public information, and unfortunately if we want to access private information we won’t be able to do it this way. Facebook only allows us to access private information if we have a Facebook application which is explicitly authorized by our users.

Authentication and Authorization

Facebook uses the OAuth 2.0 protocol for authentication and authorization.

The Facebook Authentication page explains the authentication process very well, but I’ll try to summarize the process here:

Let’s say you have an app server running in your local environment:

Register a new application to get an APP ID and APP Secret, use this settings:

  • Site URL => http://localhost:3000
  • Canvas Page => http://apps.facebook.com/your_namespace/
  • Canvas URL => http://localhost:3000/:
  • Secure Canvas URL => https://localhost:443/:

Browse the following URL:

https://graph.facebook.com/oauth/authorize?
        client_id=APP_ID&
        redirect_uri=SITE_URL/callback

The /callback route must exists.

If the user authorizes your application, Facebook will request the following URL:

http://localhost:3000/callback?code=CODE

Exchange the code for an oauth access token in the following URL:

https://graph.facebook.com/oauth/access_token?
   client_id=APP_ID&
   redirect_uri=SITE_URL/callback&
   code=CODE

Facebook will request the callback url with the access token as parameter:

http://localhost:3000/callback?access_token=token

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

Authorization process

Now your application has been authenticated and the user has authorized it, but you might be wondering what information we have access to.

The answer is: only the general information: email, name, etc.

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

Here is how you ask the user for extended permissions:

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

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

That’s basically how authentication and authorization works in Facebook.

The Open Graph protocol

So far we’ve been talking about Facebook applications, but what if we want to take advantage of all the Facebook features in our own Web pages without actually creating a Facebook application? That’s what the Open Graph Protocol was created for.

Here are some excerpts of the Open Graph Protocol documentation:

The Open Graph protocol enables you to integrate your Web pages into the social graph.

To turn your web pages into graph objects, you’ll need to add Open Graph protocol <meta> tags and the Like button to your webpages.

Here’s a list of available <meta> tags:

  • og:title - The title of your object as it should appear within the graph.
  • og:type - The type of your object.
  • og:image - An image URL which should represent your object within the graph.
  • og:url - The canonical URL of your object that will be used as its permanent ID in the graph

In addition, Facebook have extended the basic meta data to add two required fields to let us connect our pages with Facebook:

  • og:site_name - A human-readable name for your site.
  • fb:admins or fb:app_id - A comma-separated list of either Facebook user IDs or a Facebook Platform application ID that administers this page.
  • og:description - A one to two sentence description of your page.

This is a short list of tags, there are another ones you can use to define the location of a place or contact information, etc.

As you can see, this is all about the Like button and publishing stream updates when users likes our URL using the Like button, so let’s create a page and turn it into a graph object:

This would be our basic page:

<html>

  <head>
    <title>Heroku Docs & FAQs</title>
  </head>

  <body>
    <b>Heroku Docs & FAQs</b>
  </body>

</html>

And this would be our page turned into a graph object:

<html>

  <head>
    <title>Heroku Docs & FAQs</title>
    <meta property="og:title" content="Heroku Docs and FAQs"/>
    <meta property="og:type" content="blog"/>
    <meta property="og:image" content="http://ander.heroku.com/images/ruby.png"/>
    <meta property="og:url" content="http://docs.heroku.com/"/>
    <meta property="og:site_name" content="Heroku"/>
    <meta property="fb:admins" content="YOUR_FACEBOOK_ID_HERE"/>
  </head>

  <body>
    <b>Heroku Docs & FAQs</b>
    <br />
    <iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdocs.heroku.com%2F&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=80" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:80px;" allowTransparency="true"></iframe>
  </body>

</html>

Now we know all we need to start creating real Facebook applications begin learning the most important part, how to make them in Ruby (and deploy them on Heroku).

Creating a simple Facebook application

The fun part has finally arrived, we’re about to make a simple Facebook application! How simple? It will show a simple list of links to interesting articles, a Login button, and some Like buttons (We’ll show the Like buttons only if the user has logged in via Facebook).

Here’s a list of feature this application will have:

  1. It will be ready to be used as standalone application (outside Facebook).
  2. It will be ready to be used as a Canvas Application (inside Facebook)
  3. When used as a standalone application it will show a Login button (to login with Facebook credentials).
  4. When used as a Canvas Application it will login automatically.
  5. It will show a short list of links, and once the user is logged in, the user will be able to like the links and the application itself.
  6. It will show a Logout button.

Very simple.

I’ll assume you’re using Ruby 1.9.x, and that you’ve installed the Heroku Toolbelt.

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.

We’ll need to make sure we have bundler:

$ sudo gem install bundler

If you haven’t signed up for Heroku yet, now would be a good time. Click here to sign up.

What other gems are we going to use?

Installing gems with Bundler

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

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 "https://rubygems.org/"

gem 'sinatra'
gem 'sinatra-contrib'
gem 'omniauth-facebook', '1.4.0'

Let’s install our dependencies:

$ bundle install

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 Faceboku2 but you can name it whatever you want to.

These would be our application settings:

Site URL = http://faceboku2.herokuapp.com

Canvas Page => http://apps.facebook.com/faceboku (you use a different one)

Canvas URL => http://faceboku2.herokuapp.com/canvas/

Secure Canvas URL => https://faceboku2.herokuapp.com:443/canvas/

for local testing it’d be:

Site URL = http://localhost:9292

Canvas URL => http://localhost:9292/canvas/

Secure Canvas URL => https://localhost:443/canvas/

We’re using http://localhost:9292 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 name this file after your canvas application name)
  • config.ru (rackup file for Rack-based applications)
  • views/ (folder for our views)
  • views/layout.erb
  • views/index.erb

I’ll let these files look like this:

faceboku.rb

require 'sinatra'
require "sinatra/cookies"
require 'omniauth-facebook'
require './helpers/get_post'

enable :sessions

set :protection, :except => :frame_options

configure do
  set :redirect_uri, nil
end

OmniAuth.config.on_failure = lambda do |env|
  [302, {'Location' => '/auth/failure', 'Content-Type' => 'text/html'}, []]
end

APP_ID = "YOUR APP ID"
APP_SECRET = "YOUR APP SECRET"

use OmniAuth::Builder do
  provider :facebook, APP_ID, APP_SECRET, { :scope => 'email, status_update, publish_stream' }
end

get_post '/' do
  @articles = []
  @articles << {:title => 'Getting Started with Heroku', :url => 'https://devcenter.heroku.com/articles/quickstart'}
  @articles << {:title => 'Deploying Rack-based apps in Heroku', :url => 'http://docs.heroku.com/rack'}
  @articles << {:title => 'Learn Ruby in twenty minutes', :url => 'http://www.ruby-lang.org/en/documentation/quickstart/'}

  erb :index
end

get '/auth/facebook/callback' do
  fb_auth = request.env['omniauth.auth']
  session['fb_auth'] = fb_auth
  session['fb_token'] = cookies[:fb_token] = fb_auth['credentials']['token']
  session['fb_error'] = nil
  redirect '/'
end

get '/auth/failure' do
  clear_session
  session['fb_error'] = 'In order to use all the Facebook features in this site you must allow us access to your Facebook data...<br />'
  redirect '/'
end

get '/login' do
  if settings.redirect_uri
    # we're in FB
    erb :dialog_oauth
  else
    # we aren't in FB (standalone app)
    redirect '/auth/facebook'
  end
end

get '/logout' do
  clear_session
  redirect '/'
end

post '/canvas/' do

  redirect '/auth/failure' if request.params['error'] == 'access_denied'

  settings.redirect_uri = 'https://apps.facebook.com/faceboku/'

  url = request.params['code'] ? "/auth/facebook?signed_request=#{request.params['signed_request']}&state=canvas" : '/login'
  redirect url
end

def clear_session
  session['fb_auth'] = nil
  session['fb_token'] = nil
  session['fb_error'] = nil
  cookies[:fb_token] = nil
end

__END__

@@ dialog_oauth
<script>
  var oauth_url = 'https://www.facebook.com/dialog/oauth/';
  oauth_url += '?client_id=153304591365687';
  oauth_url += '&redirect_uri=' + encodeURIComponent('<%=settings.redirect_uri%>');
  oauth_url += '&scope=email, status_update, publish_stream'

  window.top.location = oauth_url;
</script>

config.ru like this:

require './faceboku'

run Sinatra::Application

views/layout.erb

<!DOCTYPE HTML>
<html>
        <head>
                <meta property="og:title" content="List of Articles"/>
            <meta property="og:type" content="website"/>
            <meta property="og:image" content="http://faceboku.heroku.com/images/heroku_logo.png"/>
            <meta property="og:url" content="http://faceboku.heroku.com/"/>
            <meta property="og:site_name" content="Heroku:Interesting Articles"/>
            <meta property="fb:admins" content="643897273"/>

                <title>Faceboku</title>
                <style>
                        body { font-family: Arial; font-size: 20px ;}
                        a { text-decoration: none; color: #333; }
                        .logout a { color: #2554C7; font-size: 15px; }
                        .article { font-size: 1.2em; }
                        .like_site { font-size: 0.8em }
                </style>
        </head>
        <body>
                <%= yield %>
        </body>
</html>

views/index.erb

<%=session['fb_error']%><br />

<% if session['fb_auth'] %>
        <a href='logout'><img src='images/fb_logout_button.png'></a>
<% else %>
        <a href='login'><img src='images/fb_login_button.png'></a>
<% end %>

<h3><%= 'Hello, ' + session['fb_auth']['info']['first_name'] + ', ' if session['fb_token'] %>Welcome to my list of interesting articles.</h3>

<table>
        <% @articles.each do |article| %>
        <tr>
                <td class='article'>- <a href='<%=article[:url]%>' target='_blank'><%=article[:title]%></a></td>
                <td>
                        <% if session['fb_auth'] %>
                                <iframe src="http://www.facebook.com/plugins/like.php?href=<%=article[:url]%>&amp;layout=button_count&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:21px;" allowTransparency="true"></iframe>
                        <% end %>
                </td>
        </tr>
        <% end %>
</table>

<% if session['fb_auth'] %>
        <hr />
        <p><span class='like_site'>Do you like this site?</span></p>
        <p><iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Ffaceboku.heroku.com%2F&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=80" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:80px;" allowTransparency="true"></iframe></p>
<% end %>

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

rackup is a command-line utility installed with the Rack gem (Sinatra depends on Rack), rackup looks for a file called config.ru, which you already have, let’s fire it:

$ rackup

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

Sinatra application!

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, as I mentioned earlier.

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.

Sinatra application inside Facebook!

And there it is!

Ok, but you can’t serve your application from your local machine all the time, you 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 you are in your application directory you’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"

Create the Heroku application:

$ heroku create THE_NAME_YOU_WANT

Now your app has been created, and assigned the URL http://THE_NAME_YOU_WANT.herokuapp.com. Time to 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, if your Canvas application is still pointing to your local machine, you now want it to point to Heroku, change it, browse to http://apps.facebook.com/your_namespace and that’d be it!

You can also download the code of this application, you’ll find some comments explaining the code in a detailed manner.

In conclusion

As you can see, building facebook applications with Ruby is simple and hosting with Heroku makes it even easier. However, if you’re building a large application you may want to consult a more robust Web framework, other then Sinatra. The most obvious choice here would be Rails 3.

Rails 3 and Facebook integration

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 some of them don’t even work with Ruby 1.9 and/or Rails 3.

The following are proven to work with Ruby 1.9.x and Rails 3.0.0.

Useful resources

Here are a few other resources you may find useful to get started integrating with Facebook, and hosting on Heroku.

Facebook

Sinatra

Rails 3

Heroku