zerosum dirt(nap)

evolution through a series of accidents

zerosum dirt(nap)

OpenID + Client Certs = Win

February 22, 2008 @ 10:46 AM by nap · 1 comment

I'm a big fan of OpenID. Or rather, I'm a big fan of what OpenID and data portability mean for the web at large in the coming white days. Single sign on and distributed identity is certainly an idea that's been long overlooked and it's time that we changed that. The next time you write a web application, ask yourself: "do my users really need yet another set of login credentials?". Then implement OpenID. It's really simple, especially in Rails. I gave a presentation on it at NHRuby last month (download PDF).

So, as gah-gah as I am over single sign on for ease of use, I'm a embarrassed to note that, like almost everyone else, I've completely overlooked client certificates for web-based authentication. By using client certificates you one-up single sign on by removing the need to use a login/password at all. This isn't new; it's something that's been available in every web browser for pretty much as long as anyone can remember. And yet I've never, ever seen a site that supports them for an authentication mechanism. Sad faces abound.

But wait! OpenID to the rescue! It turns out that MyOpenID (and a host of other OpenID providers) DO make use of them. So if you create a client certificate with your OpenID provider, you can eliminate the need to use a login/pass with any OpenID client sites. Cheers to Dr Nic Williams for digging this up. Sometimes old (and ignored) is the new new. Rock on.

More details at Dr Nic's blog.

1 comment

Plugins Are Unnecessary

February 20, 2008 @ 11:41 AM by nap · 2 comments

Plugins really are unnecessary -- Jay Fields is absolutely right. RubyGems is a great package management system and there's no reason it can't do double duty here, if we just impose a few extra restrictions on Gem/Plugin structure. There are other benefits too using Gems too, such as versioning and dependency management, which is somewhat painful in the world of Rails plugins.

Merb already uses Gems for plugins/extensions. Why doesn't Rails? Historic reasons, most likely. Rails itself predates the existence of Gems iirc. But seriously, how hard would it be to rewrite script/plugin to install a gem and unpack it into vendor? That's the first step.

2 comments

ActiveRecord: Importing YAML

February 20, 2008 @ 11:26 AM by nap · 1 comment

Backing up ActiveRecord models to YAML is easy to do, and can be convenient for creating 'templates' that can later be imported to restore basic project structure in a new database. However, the import process can be a little tricky, as the instantiated objects don't seem to respond correctly to new_record?

Here's what our YAML might look like. Note that it's a serialized CustomWidget, which is an ActiveRecord model that inherits from ActiveRecord::Base.

--- 

- !ruby/object:CustomWidget 
  attributes: 
    name: DoSomething
    updated_at: 2008-01-28 05:02:54
    description: Does something.
    created_at: 2008-01-28 05:02:54
  attributes_cache: {}

We can automatically instantiate the appropriate Ruby objects from this using the following code:

class CustomWidget < ActiveRecord::Base
end

YAML::add_private_type("CustomWidget") do |type, value|
  CustomWidget.new(value)
end

obj = YAML::load(File.open("template.yml"))[0]
=> #<CustomWidget name: "DoSomething", created_at: "2008-01-28 05:02:54", updated_at: "2008-01-28 05:02:54", description: "Does something.">
obj.save
=> true

So what we've done is taken YAML from one project and tried to use it to import the same data into another database (note that IDs are stripped). We define a transfer type for the YAML, providing a mapping to the class, and then we call YAML::load to load it up. This returns an array, in this case it contains a single CustomWidget object. Everything looks swell. We call save on the new object and it returns true.

However, if we check the count of CustomWidgets that exist in the database, we'll find that it's unaltered; no new record has been saved. It turns out that this is because the imported CustomWidget doesn't report true when new_record? is called.

obj.new_record?
=> nil

In order to save itself to the database and get a new ID, the CustomWidget instance has to first respond correctly to inquiries as to whether or not it's new. We'd like new_record? to return false. The quick-fix secret is to manually toggle the @new_record instance variable. If we do that, calling save will return true and actually save the object to the database as well this time. Big yay, right?

CustomWidget.count
=> 0
obj.instance_variable_set("@new_record", true)
obj.new_record?
=> true
obj.save
=> true
CustomWidget.count
=> 1

Yes, this is an ugly hack. Did I say ugly? I meant gross.

1 comment

Constraint-Driven Development++

February 08, 2008 @ 05:46 PM by nap · 2 comments

There was a nice writeup on ReadWriteWeb yesterday about Montreal's upcoming Blitzweekend event. Like the Rails Rumble that we organized last September, Blitzweekend is another attempt to give people a "weekend to build a functioning startup from scratch". Unlike the Rumble, it isn't a competition, and it places added value on physical proximity.

Josh Catone (of ReadWriteWeb and also RailsForum) dubs this sort of thing "organized ultra-rapid development" and notes that, against all odds, this strange weekend-startup phenomenon seems to be trending up. This is really just constraint-based development taken to the next level, and the reason it's exciting is simple: it pushes you to deliver results, immediately.

Results, of course, are what makes application development exciting; seeing a movie get automatically reencoded after upload, a search query produce a number of restaurants in my area, plotted on a map, a transaction get authorized and recorded by the third party API you're using. And later, seeing your end to end workflow in place and your first user signup. When we see results, we get motivated to work harder in order to see even more impressive results. When we don't see results, we get depressed, we step back, we overthink. Our motivation falters.

Events and contests like Blitzweekend help give developer-entrepreneurs that extra motivation kick that they often need to get over the motivation speedbump, and an opportunity to gather a team together and just go for it. If you haven't tried it, you really should. In the process you'll find out if you can work with your team in the long haul, write some (hopefully) great code, and figure out whether or not the idea has legs to stand on. If it does, you'll have visible proof of this and will probably be more jazzed than ever to continue working on it. If it doesn't, you won't have to spend any more time wondering "what if". All in 2-3 days.

(It's important to have realistic expectations of course. Are you going to be able to build the next Flickr in 48 hours? Or the next Facebook? Nope. But you sure can get a nice first iteration out there and working. Every application has to start somewhere, and if the first iteration of your idea isn't ugly and lacking important features, then there's a good chance it took you too long. Short iterations can pack a lot of result-fu ninja punch.)

Anyway, I've rambled on for a bit and I'm sorry. We'll do another Rumble, or something like it, later this year. For sure. But the reason I'm writing is this: You don't have to wait.

That is, you don't need an actual event to prove that this brand of ultra-mega CDD works.

Take the last 3-4 days of this month, of next month, of whenever. If you're a freelancer, just tell clients you're unavailable during those days. Get 3 other people to do the same thing. Agree on an idea, flesh out the basics. And just do it, Nike-style.

I'm seriously thinking about doing just this, starting at the end of February, maybe at the end of each month. Anybody wanna be on my team?

2 comments