Desligado: A simple web app supporting disconnection and deferred updates
Desligado is a proof-of-concept application made by junior developers.
The resources are cached thanks to a HTML5 Cache Manifest file and the client keeps a synced local version of the data on a HTML5 WebSQL database (or, if not supported by his browser, on his Local Storage).
Desligado is a simple item management application. Those are the functional requirements:
- Users must be able to create, edit, destroy and list items
- The item list must be updated, every time the server's database changes (without requiring any clicks)
- Users must be able to use the app offline (static contents should be presented, and dynamic contents must function) even after closing and reopening the browser
- Built with Ruby 1.9.2 and Rails 3.0.5
- Faye gem (tested with 0.5.5)
- Jammit! gem (tested with 0.6.0)
- jQuery (included; version 1.4.4)
- backbone.js (included; version 0.3.3)
- persistence.js (included; version 0.2.4)
- Entire demo app (version 1.1.8 stable)
- Rails Sync for persistence.sync
- Backbone.sync adapter for persistence.js
Supported Browsers and Caveats
Should work with, at least:
- Chrome 11+
- Mozilla Firefox 4+
It doesn't seem to work on Safari 5 (not fully tested), and Firefox will use local storage instead of WebSQL. Beware that, if the HTML layout file contains the reference to the application manifest, server pushing will not work. Comment out the reference <... manifest="application.manifest"> or just remove the public/application.manifest file to try it. This is a known issue.
The goal for this project was to create a multi-client simple web application with some basic functionalities (the creation, manipulation and deletion of shared items) that worked both online and offline.
Starting with the cache manifest, since we used Ruby on Rails for our back-end, to dynamically generate this manifest file we used the rack-offline gem, as suggested by Ryan Bates on his interesting railscast. Every time the user opens the website, all files required by the application are downloaded and saved for offline browsing. This solves the problem of accessing the static content in offline mode.
Another important aspect is that only one HTML page is fetched from the
server. This page contains the necessary components to generate four views —
index, show, edit and new. We used backbone.js and
underscore templates to build them. Backbone.js let us
implement a well-structured client-side application, but is not so
rigid opinionated as Rails. To organize our client-side code,
we followed the approach designed by James Yu on his
article about backbone.js.
Backbone is composed by several modules. It contains one module called Backbone.sync which lets us persist data through RESTful JSON requests to the server. Since we want it to work offline too, we need it to persist the data locally, using the HTML5 WebSQL technology (if supported by the browser) or the Local Storage. This would be synced to the server, if possible, when both client and server are online. This is tougher than it may look, since we are talking about a multi-client app, with desynchronized clocks, etc..
In what concerns persistence, we used persistence.js, and specifically the persistence.sync.js plugin, to keep the databases synced together. We created an adapter, a new Backbone.sync module, which maps the CRUD actions with the persistence.sync.js library's API.
Another problem is that persistence.sync was primarly made to communicate with node.js servers. Since we are using Rails, we coded the necessary mechanisms to make it work with RoR.
At last, we wanted the server to broadcast to all connected clients when one of them modifies the server's database. We integrated Faye for the server to client communication, which uses WebSockets, XMLHttpRequest (if WebSockets not supported) or JSON-P (if no other alternative is supported). We are still having some crazy issues regarding having both Faye and the application.manifest) which are listed on the bottom of this document.
To initialize the application, run:
mv config/database.yml.sample config/database.yml
mv public/application.manifest.sample public/application.manifest
rackup script/faye.ru -s thin -E production
Run the Rails sever:
A list of the current issues will be added soon.
For now, you may check our github page to keep track of all the undergoing changes.