Learning from failures: off-line support in a rails-app

An article, posted more than 8 years ago filed in rails, react, ruby, frontend, backend, offline, online, app, nodejs, ruby on rails, formdata, forms & cache.

As a web-developer you typically assume that your users are always using your app on-line. When asked a year ago to start developing an app for the art-consulting firm QKunst I was, however, specifically asked for a tool that had to work in bunkers. Bunkers where having a solid internet connection was typically the exception. No problem, I read about HTML5 and offline app-cache: I thought I could fix that. More about that soon.

Learning from failures: off-line support in a rails-app

How I face a challenge

When faced a (technical) challenge I typically search for the easiest way out: what would be the slightest change I’d have to make to my battle tested set-up to accommodate for the new challenging feature. In my case this battle tested set-up starts of with the Ruby on Rails stack, which builds on techniques that align well with how I believe the web should work too. RESTful (proper HTTP-messaging and URLs), semantic, CURL-able. And all gracefully degrading. The latter is the primary reason I’m holding back on using all-javascript-frontend-frameworks, even though in this case those could’ve made my life quite a bit easier…

Offline views

Making pages available offline shouldn’t be hard. That’s what I thought. There is was a once not deprecated spec available called Offline Web Applications, based on a cache manifest file. The ease! Simply tell the browser which pages it can cache until I tell the browser otherwise (by touching the cache file). Not. Despite some articles already warning how hard it would be to make it actually work I thought they just hadn’t applied the mechanisms properly as intended. But in the end I too ended up loading shims of pages in hidden <iframes> to be cached for later offline reuse. I got it to work, but the simultaneous request of the same page every time didn’t make the app perform any faster… at the time I wasn’t sure whether Service Workers would make it into a standard (and it is work for clients I’m doing, not some personal hobby), but it appears they are (about to, the HTML5 working group is now marking it as technology preferred over ApplicationCache).

Saving the form

Besides relatively ‘static’ pages, that I could, in the end, serve easily with AppCache, I had to deal with form-submits (luckily only for creation of objects, not updates). Maybe slightly inspired by the Service Workers I wasn’t willing to implement yet I thought it could work as follows:

  1. In case the browser cannot submit the form, store it in a local store;
  2. When the user comes back on-line get it from the store as a [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData)-object representation of the initial form;
  3. Make the exact call the browser would have made when it would’ve been on-line at the time the form was submitted by the user.

I added a field that would contain a unique key to make sure no form-submit would lead to double items in the database and slightly changed the create function at the Rails-side of things so it wouldn’t pass on redirects on the ‘background’ submits and it functions, but besides that the adjustments to the mostly standard-Rails code was minimal. Hence I could adjust the form itself any time in my trusted rails form-views, without having to worry about whether it would work off-line too (for those interested in the FormStore-code, I made it into Github gist). And although it would require javascript off-line, it would perfectly fine without on-line. And being able to use the app offline made it also easier for me to test it automatically more easily.

Hindsight

The app works, in production. It is used in bunkers with the off-line functionality. But knowing that I based it on something that was about to be being deprecated hurts. Yet at the time I didn’t think service workers would be a thing any time soon; implementing proposed, as in unfinished, standards is a serious risk too, as they might undergo breaking changes. Since the client hasn’t stopped asking for more features I soon may tweak stuff here and there a bit to prepare for the service workers. But shouldn’t I have built an all JavaScript-based app in the first place? Maybe one that ran isomorphic, both on back- and front-end? So I could offer excellent off-line support, even supporting updates? I don’t know the answer yet. I’ll keep learning. :)

Op de hoogte blijven?

Maandelijks maak ik een selectie artikelen en zorg ik voor wat extra context bij de meer technische stukken. Schrijf je hieronder in:

Mailfrequentie = 1x per maand. Je privacy wordt serieus genomen: de mailinglijst bestaat alleen op onze servers.