Pastur

Pastur provides a JavaScript pattern that lets you easily write and organize page-specific code that works properly with Turbolinks. Or, page-specific JS for turbolinks!

Inspired by Brandon Hilkert.

How it works

When navigating between pages in Rails, Turbolinks only reloads the parts of the page that change. In the typical setup, JavaScript is often only loaded when a visitor first accesses the web app, and not on every page load. This is great for page load speed while navigating around an app, but it can cause problems for things like event binding, widget initialization, etc.

Pastur provides a clean pattern to define all of the app's event bindings on a full load, then only fire them on the proper pages. It's a really simple abstraction - seriously, the readme is longer than the code.

Dependencies

  • jQuery
  • Turbolinks

Pastur is intended to enhance an out-of-the-box Rails setup with a Sprockets asset pipeline, but there's nothing in the code base that depends on them.

Installation

You've seen this before:

# Gemfile
gem 'pastur'
$ bundle install

Or:

$ gem install pastur

Add to your JavaScript manifest, after jQuery and Turbolinks:

//= require pastur
//= require_tree ./pages

You can organize and include the require_tree however you want, as long as Sprockets loads it after pastur.

Usage

// app/assets/javascripts/pages/whatever.js
App.page('.controller.action', [
  App.event('turbolinks:load', function(e) {
    // page-specific code goes here
  }),
  App.event('click', '#selector', function(e) {
    // page-specific code goes here
  }),
  // ...
]);

App.page() takes two arguments:

  1. Any valid jQuery selector
  2. An array of App.event()s, mirroring the syntax of $(document).on()

Basically all this does is inject a check for the presence of $('.controller.action') on the page before running event code. The recommended convention is to set <body class="controller action"> and define the page selector as .controller.action, but this is very flexible. Page selectors don't even have to be page-specific and should also work with partials.

Event bindings are only defined once, and all page-specific JS should only be run in an event context. Reusable components should be defined elsewhere, outside of Pastur (but called from within Pastur).

Pastur also works with CoffeeScript:

App.page '.controller.action', [
  App.event 'turbolinks:load', (e) ->
    # awesome
]

TODO

  • Generator