Subscribe to XML Feed
30 Nov 2010

Guest Post on RubyLearning: Building DSLs with yield and instance_eval

I recently wrote a guest post for the RubyLearning blog entitled “How do I build DSLs with yield and instance_eval?”. It gives a brief overview of how to use Ruby to build simple internal DSLs. Enjoy!

View Comments
03 Oct 2010

OmniAuth: Flexible, Unassuming Multi-Provider Authentication for Rack

The web application landscape has changed drastically in the past year or two. Where once every site was a silo unto itself and could reasonably expect users to create a unique login and password for each site, it is now a different story. I sigh every time I have to fill out yet another registration form, wishing instead for a simple "Connect with Facebook", "Sign in with Twitter", or "Log in with OpenID". At the same time, services are more interconnected than ever. One of the best ways to increase the popularity and viability of a new service is by piggybacking it onto the existing user bases of apps such as Twitter, Facebook, and Foursquare.

There are lots of authentication solutions out there for Rails. Many of them even have ways to connect to services such as Facebook or Twitter. But as I used these in project after project I noticed an emerging pattern: they all make too many assumptions about how I want to handle authentication in my application. Sure that makes it a quick start for the vanilla use case, but I honestly can't think of a time when I've dropped in an authentication solution and I was good to go. It's time for a change in perspective.

OmniAuth: The Unassuming Authentication Library

Today is the public release of OmniAuth. OmniAuth is a Rack-based authentication system that abstracts away the gritty, difficult parts of external authentication without assuming anything about what you actually want to do with that authentication information.

What does this mean for you? This means that you can make your app authenticate through Twitter, Facebook, LinkedIn, Google Apps, GitHub, Foursquare, and more and then have complete control from there.

Installation

OmniAuth is available as a gem:

gem install omniauth

Diving In

Using OmniAuth is as simple as using any other Rack middleware. Of course, that's because OmniAuth is simply a Rack middleware. No complicated framework-specific configuration, just a collection of middleware to take the pain out of external authentication. Let's say I have a Sinatra app that I want to be able to authenticate via Twitter or Facebook. Here's what's required:

require 'omniauth'
use Rack::Session::Cookie # OmniAuth requires sessions.
use OmniAuth::Builder do
  provider :twitter, "CONSUMER_KEY", "CONSUMER_SECRET"
  provider :facebook, "APP_ID", "APP_SECRET"
end

That's it! Now if I want to send my user to authenticate via Twitter, I send them to the URL /auth/twitter. For Facebook, /auth/facebook. The user will automatically be redirected to the appropriate site where they will be able to authenticate. Once authentication is complete, they will be redirected back to /auth/providername/callback and OmniAuth will automatically fill the omniauth.auth environment key with information about the user, so for my Sinatra client I just need to add:

get '/auth/:provider/callback' do
  auth = request.env['omniauth.auth']
  "Hello, #{auth['user_info']['name']}, you logged in via #{params['provider']}."
end

Of course, I could do a lot more than just print out the user's name. I could also:

  • Check for an existing user via the uid key of the auth hash and log them in if one exists.
  • Create a user based on the uid and information from the user_info hash.
  • If a user is already logged in, associate this new account with the user so that they can log in using either service or post to both services using respective APIs.

The point here is that OmniAuth doesn't assume that you simply want to log a user in. It lets you make that judgment call and gives you all the information you need to do just about anything you need to do.

OmniAuth works right now for a wide variety of providers, and this list will continue to grow. OmniAuth today supports:

  • Facebook
  • Twitter
  • 37signals ID
  • Foursquare
  • LinkedIn
  • GitHub
  • OpenID (meaning Yahoo, Aol, Google, and many more)
  • Google Apps (via OpenID)
  • CAS (Central Authentication Service)
  • LDAP

A Breath of Fresh Auth

OmniAuth has been my worst-kept secret library for some time now. I've been using it as the go-to authentication strategy for new projects big and small for the last few months, and it feels really refreshing to have so much control over authentication without losing the drop-in ease of use. If you need external authentication but have found existing solutions to lack flexibility, please take a look!

OmniAuth is on GitHub with a growing set of documentation on the GitHub wiki and I have also set up a Google Group to handle any questions that might arise.

View Comments
13 Sep 2010

A Web Developer Goes Native (With Android)

In the past week I’ve jumped head-first into Android development for a new Intridea project. This is my first time doing any real Android development as well as my first jump back to Java since I graduated from college. I thought it might be interesting to catalog some of my experiences developing for the platform, so here they are:

Things I Loved

Intents: Android is built on an “Intents” system. When you want the user to perform some kind of common action, you create an intent for it and activate that intent. Different applications can hook into the same intents, allowing the user to completely customize how they handle a given action.

Wow, what a brilliant system. Android is built from the ground up for insane levels of interoperability between applications. It took no time at all to get a basic QR code scanning process flowing thanks to intents, and the same went for composing e-mails and opening web pages. Literally couldn’t be simpler.

Activities: The base unit of an Android application is an activity. An Activity class is what holds the context for your application as well as manages on-screen events and more. One application may have many activities, divided up logically based on user actions.

Once I was able to wrap my head around the idea that any given “screen” is really more like an “activity” that the user performs, the logic of the application design really fell into place. I think this is a perfect level of abstraction for a mobile platform, and it really made it easy to figure out where to draw the line between one screen and the next.

On-Phone Debugging: My mouth actually dropped open the first time I plugged my Nexus One in and hit “Run” in Eclipse. In just 5-10 seconds my app was launching natively on my phone for me to test. Not only that, but I was still able to see logs and uncaught exceptions as the program ran. Running on the phone is also lots faster than running in the emulator.

Resources and NineScale: Google has come up with a very elegant solution to the idea of handling binary and other resources in Android projects. All of the resources in a directory are pre-compiled into a big reference file called R.java that simply contains access to every menu, image, string, and view that you’ve created for the application. This makes it so easy to transition between referencing resources in the XML and the code, because it all uses a similar syntax. Great stuff.

When designing views, you will often want to have image-based backgrounds that intelligently stretch to fit their contents. This is called various things in different platforms and tools (NinePatch, NineScale, 9-Slice, etc.). Google’s implementation is very simple and can be done without extra plugins from any image editor (it’s just a 1px border around an ordinary .png file). Once again, very cleverly designed.

The Overall Architecture: Android overall just feels like it was really put together with a lot of thought and care. Everything fits together really well and even people without hardly any desktop or previous mobile application development experience can pick it up relatively quickly. Also, the documentation is pretty extensive (though it would be great to have an even more exhaustive list of code examples of various aspects of the API).

Things I Didn’t Love Quite So Much

Compiling: When you’re used to viewing changes to your application just by clicking “Refresh” it can definitely feel like a waste of time to have to compile and run the app. There’s absolutely nothing that can really be done about this (it is a native app, after all) and Google has gone out of their way to make the process feel as responsive as possible, but it’s still an unwelcome break in the development cycle for someone used to working on web apps.

Where’s My CSS? I’m guessing that some people will disagree with me here, but wow did I ever miss CSS when building an Android application. CSS makes it so easy to rapidly and iteratively style things. Android has a few ways to style things that definitely help over repetitive copy and paste XML attributes, but the expressiveness and power of CSS is sorely missing from building interfaces in Android.

Exceptions: When running an application in the emulator or on the phone, I really wanted a clear and easy way to view stack traces. The LogCat view on Eclipse is the way to do this, but I found a few problems with it:

  1. The stack traces don’t list the exception you’re looking for at the top of the trace, but rather about half-way down. Takes a while to wade through and figure out what to look at.
  2. When I tried to use the debugger, I never got any useful output or link-to-line type help that I expected from a fully integrated IDE. Maybe I was using it wrong, but it didn’t help me out much.

Java: OK, OK, could take some flak for this one, but after developing full-time with Ruby for more than three years now, going back to Java feels like an unbearable chore. There’s so much boilerplate code and I found myself really missing the simple, expressive, concise idioms of Ruby. Maybe once Mirah gets a little more mature I can at least ease that part of the Android experience.

SQLite: I know that it’s the go-to solution for small, simple storage, but why on earth do mobile platforms have schema-driven data stores by default? What a ridiculously square peg to pound into the round hole of mobile data persistence. You know what the default data store for mobile ought to look like? Redis. If I had the simple data structure support provided in Redis (key-value, lists, and sets with simple combinatorial commands), I wouldn’t need anything more for 99.9% of the applications I can think of. SQL is an awful, terrible fit for mobile and I hope that one day someone realizes it.

I’m glad to see that CouchDB is trying to disrupt this space a little, and I hope that the disruption continues with more datastores and more choices being available for mobile development.

Wrapping Up

It was certainly an interesting week and I’ve been learning a lot. Android development is starting to come more naturally (looking things up on the API docs maybe every 5 minutes instead of every 30 seconds) and I’m actually starting to enjoy myself. It’s really satisfying building something that I can immediately run on my Nexus One, and I definitely look forward to working more with the platform in the future.

That being said, I don’t think I would choose to develop for mobile applications as my primary focus. While mobile development is certainly rapid compared to old-school desktop development, I still don’t think anything can match the ease and speed with which web applications can be developed. Since I’m ultimately more interested in ideas and solving the big-picture puzzles of applications than the low-level implementation details, web is still the place to be for me (for now).

And so we’ve reached the end of this rather wordy spiel; hopefully if you’re a web developer you can read this and get some idea of what it would be like to dive into mobile development, and if you’re already a mobile developer maybe you can tell me how I’m all wrong about everything I’ve just written. And maybe, just maybe, if you work for Google you’ll implement Redis as the primary datastore for Android 3.0. Hey, a guy can hope, can’t he?

View Comments
22 Jun 2010

On Android and Custom UIs

Android UI Fragmentation

Google’s Android has seen an incredible rise in popularity since its first handset was launched less than two years ago. Google has worked hard to earn that popularity, regularly releasing fantastic new improvements to the platform in the form of Donut, Eclaire, and now Froyo. Unfortunately, many users of the Android ecosystem won’t see these improvements for years, if at all. The reason? Manufacturers of Android handsets are building custom versions of the OS to add eye-candy and make the UI seem more attractive, at the expense of upgradeability.

HTC has its Sense UI and Motorola has MOTOBLUR. Samsung and Sony have also thrown their hats into the “heavily modified UI” ring. While these packages may serve to help differentiate from the competition, they are hammering the Android ecosystem by causing fragmentation (and yes, I do think that’s the right word). But it isn’t all their fault. One can certainly understand how, when competing against the likes of the iPhone, manufacturers would want to “pretty up” the Android experience. So I’ve got a few words for these OEMs, and Google as well.

Dear Google

I’m really happy that you’re ‘laser focused’ on the user experience for the next release. Now that you’ve got it humming at lightning speed with Froyo, it’s time to add some polish. Fantastic. But making a better stock UI isn’t the only thing that needs to happen to prevent this fragmentation.

You should be doing everything you can to prevent version fragmentation because it’s hurting developers and consumers. When people with G1s see “official Android Twitter client released” but can’t download it, they’ll get frustrated. They don’t know or care about the fact that the G1’s limited internal storage means that it can’t get the next upgrade, they only care that they’re supposed to have an Android but they can’t get the software they want.

Here’s my advice: take the feature lists of Sense and MOTOBLUR et al as a laundry list of areas where your API needs more robustness. If the capabilities of Sense and MOTOBLUR were exposed at an application level, this problem would simply disappear. You’ve built your platform to be backwards-compatible; if HTC wants to build a “Sense UI” app that changes the appearance of the UI and adds a bunch of widgets, and they want to make that only available on their handsets, more power to them. When the next version of Android comes out, it’ll all work seamlessly because they’ve simply built an app, like any other developer.

So keep up the good work on Gingerbread, I’m looking forward to the UI improvements. But also make your UI reachable by applications, provide hooks into the very guts of Android so that manufacturers and developers alike can really “make it their own” without building a custom ROM.

Dear HTC/Motorola/Samsung/Etc.

Thank you for making Android handsets. I’m a huge supporter of the platform, and the level of competition and innovation on Android phones has been amazing. Keep it up! But you’re doing yourselves a disservice by building these custom UIs that inhibit the Android version upgrade process.

Google has huge teams of people working to continuously upgrade the Android experience. You get the fruits of this labor 100% for free. I understand that as a handset manufacturer the idea of upgradeable phones isn’t necessarily the most appealing: if people can upgrade the software on their phones, maybe they won’t want a new one in 2 years! But trust me, you’ve shown that you’ll make the hardware good enough that people will want new phones.

Instead of locking down a handset to a specific Android version, create an unbeatable suite of applications that comes pre-loaded on your phone. Work on top of, instead of within, the Android operating system. Then you can leverage all of Google’s work and all of your own work to provide customers with a great experience. Work with Google to add pieces of API that will help you provide all of the value you want to provide; I’m sure Google would be happy to help as best it can.

Also, while I’m at it, can one of you please create a 4.3" handset running the stock Froyo UI sometime before November? I’d love to get a big-screen phone when my contract’s up, but I don’t know that I can handle dealing with these custom UI jobs. It’s just not for me.

Unicorns and Rainbows

I think that Android is a very important project that came along at just the right time. It has applications far beyond mobile handsets and we’ll begin seeing Android in cars, tablets, and more in the very near future. This will mean even more work will be poured into the Android ecosystem creating greater and greater benefits for everyone from consumers to handset manufacturers. All that needs to happen to take advantage of those benefits is for Google to help handset manufacturers free themselves of the idea that they need to “make it their own”.

I’m looking forward to the next 40 Android phones, and the 100 after that. I truly think that Android is going to dominate the mobile market five years from now (Apple will still have about the same piece of the pie, but Android will have displaced RIM and Microsoft entirely). So keep up the good work, but how about we all just get along in the meantime.

View Comments

Older Posts

MultiJSON: The Swappable JSON Handler 14 Jun 2010 Comments
AuthButtons: Free and Open Source Web App Icons 01 Jun 2010 Comments
REST isn't what you think it is (and that's OK) 29 Apr 2010 Comments
The Future's Pretty Cool (or Why I Love Ruby) 28 Apr 2010 Comments
Facebook is the Private Beta of the Semantic Web 23 Apr 2010 Comments
Announcing the OAuth2 Gem 22 Apr 2010 Comments
Ruby Quick Tip: Instant Utility Modules 19 Apr 2010 Comments
Toggle CSS3 Bookmarklet 12 Apr 2010 Comments
Ruby Quick Tip: Regular Expressions in Case Statements 29 Mar 2010 Comments
Hashie Gains a Chainable Hash 05 Mar 2010 Comments
Redfinger: A Ruby WebFinger Gem 12 Feb 2010 Comments
Simple Mustache JSON Serialization 21 Jan 2010 Comments
Compiling Mustache Views for Mustache.js 18 Nov 2009 Comments
Hashie: The Hash Toolkit 12 Nov 2009 Comments
Rails Quick Tip: Readable Conditional Validation 03 Nov 2009 Comments
TweetStream: Ruby Access to the Twitter Streaming API 22 Sep 2009 Comments
CouchDB-Lucene, CouchDBX, and CouchRest 21 Sep 2009 Comments
A Fresh Coat of Paint 20 Sep 2009 Comments
Good Idea, Bad Idea: Rails Rumble Post-Mortem 24 Aug 2009 Comments
Quick Tip: Railsy Array Checks in jQuery 19 Jun 2009 Comments
Make it so with RSpec Macros 15 May 2009 Comments
TwitterAuth Supports 'Sign in with Twitter' 17 Apr 2009 Comments
Present.ly Nominated for the WebWare 100 31 Mar 2009 Comments
Using Git Submodules for Shared Application Components 25 Mar 2009 Comments
TwitterAuth: For Near-Instant Twitter Apps 23 Mar 2009 Comments
Yet Another Twitter Monetization Strategy: 'Claimed' Hashtags 18 Mar 2009 Comments
The Case For GitHub Canonization 03 Mar 2009 Comments
Quick Tip: Rails URL Validation 18 Feb 2009 Comments
Utilize Canonical URLs in Your Rails Apps 13 Feb 2009 Comments
Outsource Your Blog 11 Feb 2009 Comments
Open Source Is Amazing 11 Feb 2009 Comments
Moving to Jekyll 10 Feb 2009 Comments
It's No Joke - Real-Time Search is a Big Deal 09 Feb 2009 Comments
SASS: The Better, More Powerful CSS 04 Feb 2009 Comments
Use MacFUSE to Make a Boxee Torrent Dropbox 02 Feb 2009 Comments
The Case For Web Applications 02 Feb 2009 Comments
HasAvatar: Defining an Application Vocabulary 28 Jan 2009 Comments
Twitter Search Plus: Find Replies Inline With Twitter Search 22 Jan 2009 Comments
Sort Your Files By Date 04 Dec 2008 Comments
The Importance of External Downtime Resources 28 Nov 2008 Comments
Hacking the Mid-End (Great Lakes Ruby Bash Edition) 11 Oct 2008 Comments
Colorist: Color Manipulation for Web Heads 18 Aug 2008 Comments
Fetches: Bringing Your ActionController Its Slippers 28 Jul 2008 Comments
Using HTTP Status Codes for Rails AJAX Error Handling 23 Jul 2008 Comments
UberKit Update: UberForms to Ease Form Building 14 Jul 2008 Comments
UberKit: Building a Rails UI Swiss-Army Knife 07 Jul 2008 Comments
What the World Needs Now is CSS3 02 Jul 2008 Comments
Using RSpec and Autotest While Writing Rails Plugins 25 Jun 2008 Comments
SubdomainFu: A New Way To Tame The Subdomain 23 Jun 2008 Comments
GemPlugins: A Brief Introduction to the Future of Rails Plugins 11 Jun 2008 Comments
ActsAsTaggableOn Grows Up 09 Jun 2008 Comments