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 :)