Tuesday, June 22, 2010

Integrating Facebook into Rails

Recently, I integrated facebook’s new Graph API into Noteleaf. Though it’s far far easier than the old API, which almost didn’t warrant a blog post. However, authorization took a little bit of figuring out, so I thought I’d share.

If you’re using the languages blessed by Facebook, such as PHP, Javascript, Python, Objective-C and Java Android, then there’s already an SDK for you.

However, as a rubyist, we were on our own. Since we’re using Authlogic, we should be able to find a plugin for authenticating facebook.

On the Authlogic docs, it has authlogic_facebook_connect listed. It also depends on the most popular ruby gem for facebook integration, facebooker. However, facebooker’s documentation is shabby and the tutorials are out of date. I didn’t want to be digging around in something that wasn’t our core value proposition. So I didn’t end up going that route.

I was digging for alternatives, but in all the wrong places. It wasn’t until I was reading the facebook api docs more carefully, that I realized I should be looking for an OAuth2 module for Authlogic. After that, it was a breeze.

The instructions for authlogic_oauth2 are pretty clear, but here’s some tips. Beyond the instructions in authlogic_oauth2, make sure you set the oauth2_scope to request offline_access. If you don’t, when the user’s facebook session expires, your oauth_token that you stored in the user’s database will be expired. That means that after a while, the user won’t be able to log back in without requesting another token.

class UserSession < Authlogic::Session::Base oauth2_scope          "offline_access,email" end

And if you do store the user’s facebook id locally, make sure it’s a big int.

class AddFacebookIdToUser < ActiveRecord::Migration def self.up add_column :users, :facebook_id, :bigint, :limit => 8 end  def self.down remove_column :users, :facebook_id end end

which you can subsequently set in a before_create filter in User model.

class User < ActiveRecord::Base before_create :populate_oauth2_user  private def populate_oauth2_user return if oauth2_token.blank?  response = oauth2_access.get('/me') user_data = JSON.parse(response) if !user_data['id'].blank? self.facebook_id = user_data['id'] end end end

You may also want to consider using the provided javascript SDK. That way, you’d be able to load your page first, and have the client’s browser request the rest of the facebook data, so it appears you page loads faster.

Posted via web from The Web and all that Jazz

Monday, June 21, 2010

APK Downloads for Android Projects - GitHub

For all you Android developers out there, we now will automatically detect when you upload an Android package (.apk) file and will give you a QR code page link on your download page list, like this:

Posted via web from The Web and all that Jazz

Friday, June 18, 2010

Boosting my social memory

I've changed what I'm working on, as I decided to table Graphbug as a side project. Everyone said public data would be a good thing for lay-people to browse through easily, but no one could specifically think of what datasets they'd want. Like going to the dentist, it's something that's good for other people, but not themselves. In hindsight, I should have picked data to visualize for apartment hunting and moving as the niche problem to solve. Otherwise, I was trying to boil an ocean.

But that's ok, as I've moved on to found a startup to do something I've really wanted for a long long time. We're working on Noteleaf, something to boost your social memory by making it easy to take notes and follow up on the people you know and meet.


I have terrible social memory. It's not just not merely remembering people's names. That can be done with a little bit of effort and mental hacks. I can't remember what other people are doing in their lives, whether they're graduating, moving, or looking for a job. I can't remember what the name of their kids are, their girlfriend, or fiancé. 

One fine day in May, I called my friend Amy up and said, "Congratulations!". She replied enthusiastically, but puzzled: "Thanks! But for what?" I told her, "For graduating dental school." She laughed, "Ahh, thanks, but I graduated last year, and you called me then to congratulate me too." 

It's not that I don't care. I just can't remember. I have disparate groups of friends, so I don't get gossip about other friends to remind me of what they're doing. My friend ranges from college-aged to recent parents with kids. With everyone in different stages of life, I can't keep track. I have enough things to keep track in my own life that it's hard to have bandwidth to think of others.

Thoughtfulness has to be both relevant and timely. Relevant, because it makes no sense to congratulate someone on their new job when they are still at their old one. Timely, because wishing someone happy birthday on a day that's not their birthday doesn't have the same effect.

We wrote Noteleaf to help us do both. By taking simple notes about others, you can recall what you talked to them about last time and start right where you two left off. And by scheduling automatic followups you can be thoughtful on your own time, and they get it when it's timely for them.

Facebook has been nice in getting news about friends old and new. However, not everything you'd want to remember about them comes on the news feed. There's a transient nature to the news feed, that chances are, you won't remember whether a friend left for vacation this week or next, and you meant to give them some travel tips.

With business contacts, you may not even be facebook friends. While important, you may meet them even less, so the details of their lives are even more fleeting. It's a leg up to getting things done, when you can remember who they are and what's important to them.

Noteleaf is still in closed beta for the time being, but just put yourself on our email list, and we'll let you know when we open the gates. In the meanwhile, we also started a noteleaf blog.

For all of our busy lives, I think it's important that we are involved in the lives of those we care about, and keep making connections to new and interesting people. Because beyond the glory of work and career, the trappings of fame and accolades, and enticement of money and prestige, deep connections to people we care about is one aspect of life that fulfills us and makes us whole.

Posted via web from The Web and all that Jazz

Sunday, June 13, 2010

How to generate forms in rails helpers

This is more of a note to myself than anything, since I find myself having to generate forms from helpers in Rails every once in a while. This is for Rails 2.3.5. I don’t know if Rails 3 has this problem.

I wrote my own in-place editor for model fields, and it generates a form through a helper.

 1 # used internally to generate the form for the en_place editor  2 def en_place_form(record_or_array, field_name,   3                   options = {}, html_options = {})  4   # process the options, and other misc details  5   form_block = proc do  6     form_for(record_or_array, :html => html_options) do |f|  7       concat(f.text_field field_name, :class => "en_place")  8       concat(f.submit "Update")  9     end       10   end 11   is_haml? ? capture_haml(&form_block) : capture(&form_block) 12 end

All you have to do is capture a block that calls form_for or form_tag. And then inside of the form, you can to call concat on the fields that you want inside of the form.

Then lastly, you have to capture the block. If you’re using haml, you have to call capture_haml() instead.

Posted via web from The Web and all that Jazz

Saturday, June 05, 2010

A left merge versus a right merge

Recently, I found out that you can set the default winner in a merge for a hash. I wasn’t going to write about it since I figured it was pretty basic. But then again, I hadn’t written in a while. Been busy. So something easy to get me back on the wagon.

I’ll call it a left merge and a right merge. Let’s say we have some options, like default options and new options in a method, and we want merge them together, where options override default options, but you store it into options.

1 # some options 2 default_opts = { :a => 1, :b => 2 } 3 opts = { :b => 3, :c => 4 }

Well, the normal way of merging things won’t work:

1 # the normal default merge 2 opts.merge!(default_opt) # => { :a => 1, :b => 2, :c => 4 }

Well, that’s not right. We want the default options to be overridden by the new options and store it in the opts variable. We could do it like this:

1 # one way of doing things 2 opts = default_opts.merge(opts) # => { :a => 1, :b => 3, :c => 4 }

But then here’s another

1 # the other merge 2 opts.merge!(default_opts) { |k,o| o } # => { :a => 1, :b => 3, :c => 4 }


Posted via web from The Web and all that Jazz

Tuesday, June 01, 2010

BrowserCouch is CouchDb for browsers

BrowserCouch Documentation

BrowserCouch is an attempt at an in-browser MapReduce implementation. It's written entirely in JavaScript and intended to work on all browsers, gracefully upgrading when support for better efficiency or feature set is detected.

Not coincidentally, this library is intended to mimic the functionality of CouchDB on the client-side, and may even support integration with CouchDB in the future.


This prototype is intended as a response to Vladimir Vukićević's blog post entitled HTML5 Web Storage and SQL. A CouchDB-like API seems like a nice solution to persistent storage on the Web because so many of its semantics are delegated out to the JavaScript language, which makes it potentially easy to standardize. Furthermore, the MapReduce paradigm also naturally takes advantage of multiple processor cores—something that is increasingly common in today's computing devices.

Things to do

To learn how to use BrowserCouch, check out the work-in-progress tutorial.

Aside from that, you can run the test suite and the semi-large data set test, though they're not particularly exciting. In the future, we'd like to make CouchDB's Futon client work entirely using BrowserCouch as its backend instead of a CouchDB server, but that's a ways away.

If you'd like to see more code samples of what the BrowserCouch API currently looks like, check out the annotated source code for the test suite. You can also read the primary source code documentation for more on BrowserCouch's implementation.

This is really awesome. I thought about doing this, but figured it was a massive undertaking. I'm glad someone's doing it. CouchDb's replication features (while not implemented yet in BrowserCouch), is something to really look forward to, especially if it's available for mobile browsers.

Posted via web from The Web and all that Jazz