Sync - Realtime Rails Partials

Sync started as a thought experiment that is growing into a viable option for realtime Rails apps without ditching the standard rails stack that we love and are so productive with for a heavy client side MVC framework. Sync lets you render partials for models that, with minimal code, update in realtime in the browser when changes occur on the server. We’ll run through a breakdown after the video, but first let’s see it in action:

Sync provides:

  • Built in channel security through hash message authentication codes for all partial channels
  • Realtime updates of partials in place in the DOM when the sync’d model is updated in the controller via sync_update @model
  • Realtime removal of partials from the DOM when the sync’d model is destroyed in the controller via sync_destroy @model
  • Realtime appending of newly created model’s on scoped channels via sync_new @model, scope: @some_scope
  • JavaScript/CoffeeScript hooks to override and extend element updates/appends/removes for partials
  • Support for Faye and Pusher

How it works

On the server

When changing your partial rendering from <%= render partial: %> to <%= sync partial: %>, Sync will render out your partial surrounded by two script tags, denoting where this partial’s DOM element begins and ends and creating a new partial to subscribe to specific update/destory events for the sync’d resource. Elements are identified in the DOM by unique, secure selectors hashed from the partials name, model id, and the auth_token set in the sync configuration. This allows only authorized visitors to listen on our partial update channels.

After setting up your realtime partials in your views, the only missing step is to notify listeners via the controller that we either have new HTML for their respective resources, or their resource has been destroyed, and they should now be removed from the DOM via sync_update @model, sync_destroy @model, or sync_new @model. When these methods are called, Sync will render all partials for the resource in app/views/sync/[model name pluralized]/ to a string and publish each event via a message to our Sync client (either Faye or Pusher). Under the hood, this equates to:

On the client

In practice, the markup tree will like something like this for a list of realtime table rows:

Rendering a script tag before and after our partial markup allows a selector to be built for this chunk of DOM, while leaving your styling unaffected by the additional rendered tags. When the partial receives a message from the server that its resource has been updated, it is handed the updated HTML for that partial and simply replaces its element with the new HTML. Similarly, when receiving destroy events on the destroy channel, the partial simply removes the element from the DOM. The Partial coffeescript class itself is rather basic as its role to only identify a DOM range and listen for specified events. Upon receiving events, it delegates update, remove, and insert actions to a Sync.View instance.

Moving forward

As this is the first public release of Sync, expect rapid developments of new features as we explore and integrate broader use cases. I would love to get feedback on use cases that Sync currently does not address and to see how far we can take this approach. Go have some fun making your app realtime and Let me know what you think on twitter, or checkout the codebase on github. Happy coding :)