Pushing along the Rails (fixed)

Costa Shapiro
2 min readNov 25, 2014

--

(with actual working code!)

N.B. The first version of this memo described an untested and flawed solution, my apologies for that. Having fixed the technique, as presented below, I am currently looking into Firebase-like technologies which seem to have a better fit for the case.

Real-time apps are called just apps nowadays, so if ye don’t have no realtime in yer app, yer app is no app at all matey. Luckily, the community and the services are widely available, making real-time server-client communication almost a snap.

My current web application dev platform is pretty standard Rails on one side and Backbone & friends on the other. The service which is found fit to carry the messaging back to the client is Pusher and it has both a Ruby gem for the serverside and a Backbone plugin for the clientside; it even has a nice development server for local/offline testing with webhooks and whatnot.

This is an overview of the Pusher integration in a realtime-data web app.

I’m not mentioning the installation procedures which come with the components above, hopefully, they’ll work for you as smoothly as they did for me.

Disclaimer: the Backpusher plugin — in its simplicity — doesn’t currently have any means of sorting messages, so the order you push your messages in is important. The shown technique — in its simplicity — may theoretically lead to some temporarily data corruption on the client due to the deliberate lack of synchronisation between different nodes in such distributed environment; you should account for this and see if it’s any major problem to your app in real life.

If you’re using Heroku, the straightforward way to start up is to add the Pusher plugin, then go to its settings, grab the development API URL and set PUSHER_URL in your development environment (e.g. through .rvmenv).
This is pretty much all you need to initialise the Pusher gem actually — even easier than the (quite comprehensive) official documentation says it is.

And now…

The serverside:

Rails model notification concern employing Pusher: app/models/concerns

…which should be included in the pushed model which should have #pusher_channel defined to something unique (because there’s a channel per model per user in this setup) and hard to guess (like including the owner user’s session key, because you don’t want anyone else listening to that channel).

Note that you may want to customise your model’s #as_json — to control what’s passed on the wire explicitly — the only required field is id.

Also note, you should have a REST JSON-capable controller for the pushed model just as Backbone needs.

The clientside:

Rails: asynchronous pusher clientside initialisation snippet

…which uses a simple async init mechanism:

Client-side asynchronous pusher init utility: app/assets/javascripts

…and has an optional fake pusher support, see below.

The specs:

Attention: specs are omitted for brevity, but are quite easy to write with a stub or two. This may give you some direction:

Rails/Rspec context for stubbing Pusher in tests: spec/support

The fake:

For the sake of local development as well as feature/integration testing, here’s a quick & dirty integration of a(n almost real) local pusher server.

Rails: loading asynchronous Pusher client-side (js) module: in app/views/layouts/application.html.haml
Rails-Pusher integration: config/initializers

The end!

P.S. Gists have been somewhat updated, plus see notes.

--

--