Introducing Flow on FluidDB
Since the end of last year I've been spending quite a lot of my spare time experimenting with FluidDB as a platform for web-development. The result is a still incomplete application that I call Flow (the source-code is hosted on GitHub).
Flow is a simple "show and tell" project to demonstrate how to write small javascript based applications for interacting with FluidDB. The aim is for Flow to become an application for writing javascript based applications with FluidDB.
I'll let you pause a minute while you work out the circularity of that last sentence. ;-)
To make things clearer I've cobbled together a short screen-cast that attempts to demonstrate what I've been up to. (It's very rough and ready, but you'll definitely get the idea.)
As I mention in the screen-cast, Flow makes use of the Sammy javascript framework, a modified jsFluidDB script, jQuery and FluidDB
itself (for hosting and data storage).
It's VERY incomplete, hardly tested properly, extemporised (rather than designed) and needs a lot of TLC – just a proof of concept really. Nevertheless, as the video demonstrated, you can:
- Sign in/out
- View, create, edit and delete namespaces/tags
- Edit tag values for mime-types text/* in all browsers and the ability to do the same for image/* and application/pdf and application/vnd.ms-powerpoint values in Firefox version 3.0 and above (more on this later).
- Search for objects using the simple query language that comes with FluidDB.
To use it properly you'll need to register for a username and password here:
http://fluidinfo.com/accounts/new
Here are some of the development highlights…
FluidDB as a Server
Lets just remind ourselves of how FluidDB is organised from the point of view of data / schema:
- Objects represent things in FluidDB.
- Users define attributes to attach to objects – these are tags that can be organised with namespaces.
- When a tag/attribute is associated with an object it can (optionally) hold a value.
- The value of a tag/object association can be anything but you can (optionally) specify a mime-type for each value.
This is all we need to understand for now. (FluidDB's "killer feature" is actually its permissions system and the implications thereof. It is so important that I'll save that topic for its own blog post later. But one step at a time…)
So how does FluidDB act as a web-server..?
Simple really (and apologies if this is too simple an explanation – I don't like to assume too much technical expertise)...
Remember that FluidDB is RESTful in that its API is exposed through the HTTP protocol (y'know, that thing the World Wide Web is built out of). So, if I want to retrieve the value of a tag/object association I simply HTTP GET a URL – just like a web browser does for web-pages.
So how about I create an object to represent my web-application, add a bunch of namespaces and tags that map to the names of the files and directories needed for the application to work and then associate these tags with my application's object? Of course, I make sure the tag/object values are the contents of the files and that the mime-types are set properly (e.g. values for tags mapping to .html files have the mime-type "text/html").
This means that if a browser does an HTTP GET request to the path for a tag/object value within FluidDB and the mime-type for the value is set to "text/html" it'll display it as a web-page. The same goes for javascript (application/x-javascript), CSS (text/css), images (image/*) and anything else (application/pdf for example).
Hey presto… FluidDB is a universal web-server.
Sammy.js
So we have a server for our application, but FluidDB doesn't allow any server-side scripting. This means we need to put our application's logic somewhere else – the only other place being on the client's browser.
Happily, we can use a browser's Javascript capabilities for this and doing so is not so much a leap as other well-known web-applications already do this (GMail, Google Docs, Zoho and so on).
What is more, the guys in the CouchDB project have been thinking along similar lines for a while and Aaron Quint has developed a javascript framework for browser-side web applications called Sammy.
Sammy is a tiny javascript framework built on top of jQuery. Because of a clever "hack" it is able to "trap" GET and POST requests from a page and handle them with javascript functions associated with "routes". It's certainly packed full of features for such a small application and I've been hacking away with a maniacal grin on my face as I've been exploring Aaron's work.
If you've still not figured out why this is important, take a look at these two images Aaron has created (extracted from this presentation and used with permission) to show the difference between "regular" web-application development and that promoted by CouchDB and (now) FluidDB:
Sammy allows us to live in a Lisp like "code is data" world with no web-server / web-framework playing piggy-in-the-middle. The database is the server and the framework is Sammy-as-data running on the client.
HTTP PUT, Forms, Mozilla & Binary Data
In order to create or update a tag on an object the API requires a PUT request containing the appropriate value. Unfortunately, if the data we want to send is not text based we have a problem.
The usual way to upload binary data is to use an HTML input element with the "type" set to "file". Unfortunately, forms can only use the POST and GET HTTP verbs (this seems an amazingly bad decision – surely they should only support POST and PUT..?).
Rather than change the whole Internet I investigated how to get at the raw data from the request with Javascript and re-frame it as a PUT request to FluidDB. It turns out this is impossible except for users of Firefox.
Since version 3.0 (or 1.9 of the Gecko engine that Firefox uses) it has been possible to do this with the getAsBinary() function. In fact Mozilla have also provided the rather useful getAsDataURL() and getAsText() functions too. These are definitely non-standard and more information about them can be found on Mozilla's website.
You can see how I did it by looking at the "upload_to_mozilla" function in the tag_value_app.js file in the javascript directory/namespace.
Unfortunately, this means I'm stymied for the other browsers and I'm not sure of the best solution. Of course, extracting textual data from a form is easy on all browsers so this only affects binary data. Nevertheless, it's a problem that probably should be solved if such database-hosted applications become popular.
That's all (for now)...
I'll keep plugging away at Flow and will post updates on Twitter.
I also have to give a presentation in March at ThoughtWorks in London about FluidDB. I was thinking… it might be fun to create a "presentation" application with FluidDB and Sammy. Something along the line of DOM slides, AJAX-S or S5.
Who knows… it might actually be useful…
Oh, hang on… some guy called Aaron Quint has already done it with CouchDB.
;-)