WARNING: These instructions are for Facebook version 1 (not Facebooker2). Since last year, I have moved toward using a different gem for this due to Facebooker’s lack of documentation. Working on a new blog post detailing that.

So you want to write a Facebook app written in Rails? Well, the good news is that it works. The bad news is that out of the box Facebook didn’t quite design their platform to work with some of the core concepts (namely, REST) of Rails.

You need to use a great plug-in called Facebooker. Here is a quick set-up guide to help you along, with some tips and pitfalls.

1. Install these two gems

sudo gem install facebooker htmlentities

2. Install the plugin

script/plugin install git://github.com/mmangino/facebooker.git

3. add this to your environment.rb file

 config.action_controller.allow_forgery_protection = false
 config.gem “htmlentities”
 config.gem “facebooker”

4. configure your facebooker.yml. See the Facebook developer site for your site’s API key and secret. You’ll also put in your canvas path here.

In facebooker.yml, your canvas_page_name is the part first part after apps.facebook.com/ where your users will use your app. You do not need a leading or trailing slash. (In Facebook developer, go to Edit Settings > Canvas > “Canvas Page URL”).

Your callback_url is the URL name where you will operate (include http:// ) and under your facebooker.yml settings is called “Canvas Callback URL.” You don’t need a trailing slash here either. Your users won’t see this URL, because only Facebook will talk to this domain. Therefore, you can safely have it be a subdomain.

development:
api_key: XXXXX
secret_key: YYYYYYY
canvas_page_name: mygreatapp
callback_url: http://www.yourdomain.com
pretty_errors: true
set_asset_host_to_callback_url: true
tunnel:
  public_host_username: your_username
  public_host: the_tunnel_host
  public_port: 3000
  local_port: 3000
  server_alive_interval: 0

5. I found that your app has to be developed live (or at least live on a dev server). The only other way to develop would be to re-route the network where your local is to be the end-point for the the call from Facebook to your app.

I found that doing it this way was a pain, so I devised this lightweight hack to let you push all your changes up to your github account, then add a post-receive hook in your github repo to trigger your development environment to update itself for every commit you make. Tedious, I know, but effective. (Optional)

 # add this to your ApplicationController
 def github_pull
  output = “Pulling from github…”
  output << `/opt/local/bin/git pull`
  output << `touch tmp/restart.txt`
  render :text => “”
 end
// add this to your routes.rb file
 git hub pull route
 map.connect ‘/github_pull’, :controller => “application”, :action => “github_pull”

7. Create a facebook_controller.rb in the app/controllers folder. I highly recommend this for one important reason: Your app might have parts of it that you don’t want bypass the Facebook authentication (for example, you go to create some kind of an AdminController). All other controllers (the ones your users interact with) should be inherited from the FacebookController (instead of the ApplicationController). That way, you’ll get to keep the Facebook logic inside of this FacebookController. If you have a controller you want outside of the Facebook part of your app, you can make it inherit from the ApplicationController as you normally would.

class FacebookController < ApplicationController
  helper :all
  layout “application”
  before_filter :current_user

  protect_from_forgery
  ensure_authenticated_to_facebook
  ensure_application_is_installed_by_facebook_user
  filter_parameter_logging :fb_sig_friends, :password
  
  def current_user
   @current_user ||= User.find_or_create_by_facebook_uid(params[:fb_sig_user])
  end
end

8. Map your root route in routes.rb (you have to figure that out yourself based on what you want your canvas page to be).

9. Configure your database.yml, .gitignore, etc.

From here, you can start generating your models. You’ll notice that I added to the FacebookController the assumption that you have a User model with a facebook_uid attribute, so go ahead and generate one now if you haven’t already.

script/generate facebook_scaffold User facebook_uid:integer

Note: You cannot use the normal scaffold generator. That’s because your
respond_to block in your controllers must have a format line for fbml. This suspends the normal rules of REST and allows all actions to be POST actions. If you don’t do this, you get:

406 Not Acceptable

Your controllers should look like this:

  respond_to do |format|
   format.fbml
  end

And your templates should end with “.fbml.erb”. You can just go ahead and rip out those format.html and format.xml calls – unless you have some funky kind of hybrid app that works in & out of Facebook, you don’t need them.

=== TIPS ===

You can access any of the settings in config/facebook.yml but using the FACEBOOKER global hash, as in:

FACEBOOKER[:callback_url]
FACEBOOKER[:canvas_page_name]

If you are using Rails with Passenger and you get this error:
Undefined method rewind and rails 2.3.3

– update passenger to the latest version
sudo gem update passenger
sudo passenger-install-apache2-module

By Jason

Leave a Reply

Your email address will not be published. Required fields are marked *