Life hacker

Main menu

Post navigation

How to integrate Facebook Connect with a Rails app

Update: I have written up another post for using Devise and Omniauth, and you can find it here. Facebooker is no longer maintained.

Top of my to-do list was to integrate Facebook Connect with my Rails app, since 1) there are A LOT of people using Facebook and 2) having to register to post or edit could be an obstacle in getting more users to use my site.

I looked on the web for a while, and found a great example by Stuart Eccles at Made by Many. It’s an awesome tutorial, but it’s for restful_authentication. I don’t use it, so I had to modify it a little bit. Also, I added a step to ask a user to pick a username. So the following instruction is basically modification of Stuart’s.

Without further ado, let’s begin.

1. Setup Facebook Application page

1.1. Go to this page, and enter a name for your application. I named mine “Playgrounds_R_Us”.

1.2. Make a note of Application ID, API Key, and Secret. You need it for facebooker.yml later.

1.3. Next is Authentication section. Here what’s important is Post-Authroize and Post-Remove Callback URL. They refer to a web page a user will be taken to after logging into and logging out of Facebook account. While testing, I left it at “http://127.0.0.1:3000”.

1.4. I also used the same URL (http://127.0.0.1:3000) for Canvas Callback URL in Canvas section and Connect URL in Connect section.

1.5. Then you are pretty much set with configuration on Facebook side.

4.1. Add the following two lines right after <body> tag in app/views/layouts/application.html.erb.

<%= fb_connect_javascript_tag %>
<%= init_fb_connect "XFBML"%>

4.2. Make sure you have the following line between header tags in app/views/layouts/application.html.erb.

<%= javascript_include_tag :defaults%>

4.3. Also add the followings in the ApplicationController in app/controller/application_controller.rb. When user logs into Facebook account, :facebook_session will have all the information about the user. :facebook_session is utilized a lot.

before_filter :set_facebook_session
helper_method :facebook_session

4.3. Also in ApplicationController, where I see if a user is logged in or not, I had to put additional code to see if it’s a facebook user. It’s a facebook user, if facebook_session is successfully created.

It could have normal facebook login button options like :size and :background. Check here for the options.

When a user clicks on the button, it will bring up a popup window where user can log in. After the user is logged in, link_user_accounts action in user controller will either create a new user with Facebook credentials or recognize a user as existing user by either email hash code or facebook user id. It will be covered later.

And also make sure the following line is added to the routes in config/routes.rb.

map.resources :users, :collection => {:link_user_accounts => :get}

4.5. In User model in app/models/user.rb, you can just use the same code as Stuart’s.

after_create :register_user_to_fb
#find the user in the database, first by the facebook user id and if that fails through the email hash
def self.find_by_fb_user(fb_user)
User.find_by_fb_id(fb_user.uid) || User.find_by_email_hash(fb_user.email_hashes)
end
#Take the data returned from facebook and create a new user from it.
#We don't get the email from Facebook and because a facebooker can only login through Connect we just generate a unique login name for them.
#If you were using username to display to people you might want to get them to select one after registering through Facebook Connect
def self.create_from_fb_connect(fb_user)
new_facebooker = User.new(:username => "fb_#{fb_user.uid}", :password => "", :email => "")
new_facebooker.fb_id = fb_user.uid.to_i
#We need to save without validations
new_facebooker.save(false)
new_facebooker.register_user_to_fb
end
#We are going to connect this user object with a facebook id. But only ever one account.
def link_fb_connect(fb_id)
unless fb_id.nil?
#check for existing account
existing_fb_user = User.find_by_fb_id(fb_id)
#unlink the existing account
unless existing_fb_user.nil?
existing_fb_user.fb_id = nil
existing_fb_user.save(false)
end
#link the new one
self.fb_id = fb_id
save(false)
end
end
#The Facebook registers user method is going to send the users email hash and our account id to Facebook
#We need this so Facebook can find friends on our local application even if they have not connect through connect
#We hen use the email hash in the database to later identify a user from Facebook with a local user
def register_user_to_fb
users = {:email => email, :account_id => id}
Facebooker::User.register([users])
self.email_hash = Facebooker::User.hash_email(email)
save(false)
end
def facebook_user?
return !fb_id.nil? && fb_id > 0
end

But, mine had one difference. Since I didn’t use restful_authentication, my user model was different – no :name and :login fields. So, I changed mine to reflect my model.

Here, again mine is a little different, because I wanted to ask user to pick a username instead of temporary “fb_[numbers]” type of username. So, after a local user account is created, I direct the user to edit_user_path.

4.7. In Edit view of User controller, I see if it has a temporary username or not. If it does, I only ask user to pick a pretty username and perhaps location, which is required when registering in an old way.

4.10. Last, but not the least, I found that even if a user is logged out from facebook, its cookie causes the site to think the user is still logged in, and refresh will bring the user back in (from the dead). To kill the ghost, make sure you have the following lines in the Destroy action in Session controller in app/controller/sessions_controller.rb.

Simply want to say your article is as surprising.
The clearness in your post is simply spectacular and i could assume you are an expert
on this subject. Fine with your permission let me to grab your RSS feed to keep up to date with
forthcoming post. Thanks a million and please carry on the rewarding work.

I like the helpful information you provide for your articles.
I’ll bookmark your blog and check once more right here regularly. I am relatively certain I will be informed a lot of new stuff right right here! Good luck for the next!

Thanks so a immense deal pertaining to charitable me an inform lying
on this matter on your web-site. Please realize that if a completely new post
becomes available or when any improvements occur with the
recent article, I would consider reading more and finding out how to make first-class using of those methods you discuss.
Thanks for your efforts and consideration of other individuals by creation this blog available.

I am curious to find out what blog platform you’re utilizing? I’m experiencing some small security problems with my latest site and I would like to find something more secure.
Do you have any suggestions?

Howdy, i read your blog from time to time and i own a similar one and i was just
wondering if you get a lot of spam comments? If so how do you stop it, any
plugin or anything you can recommend? I get so much lately it’s driving me insane so any assistance is very much appreciated.

Hi Ryan, I use Akismet WP plugin (since I am using WP), and it works quite well. I also moderate comments so that I don’t let any spammer leave a comment. I need to update this blog and reply to more comments….

Howdy! This article couldn’t be written any better! Looking through this article reminds me of my previous roommate! He continually kept talking about this. I most certainly will send this article to him. Fairly certain he’ll have a great read.

Hello! Someone in my Facebook group shared this site with us so I
came to check it out. I’m definitely enjoying the information. I’m book-marking and will be
tweeting this to my followers! Great blog and amazing design and style.

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

To create code blocks or other preformatted text, indent by four spaces:

This will be displayed in a monospaced font. The first four
spaces will be stripped off, but all other whitespace
will be preserved.
Markdown is turned off in code blocks:
[This is not a link](http://example.com)