Using spring with pow!

The other day I was a bit sad for I was aware that pow (the web server) wasn’t leveraging spring (the Rails preloader) with its fast load times.

Fixing config.ru

Luckily this deficiency is easily fixed by adding the spring snippet to your config.ru:

# This file is used by Rack-based servers to start the application.

begin
  load File.expand_path('../bin/spring', __FILE__)
rescue LoadError
end

require ::File.expand_path('../config/environment',  __FILE__)
run Rails.application

Enter ju-jist, the gist runner

Neo: Ju jitsu? I’m gonna learn Ju jitsu?

Forewords

In the last article we explored the internals of D3.js, the data visualization library.
In doing that we ended up with a number of files in a gist.

This morning I thought it’d be nice to put up the thing into one of those JavaScript fiddle sites, I looked up a bunch of them: CodePen, JSFiddle, JS Bin but none of them allowed for arbitrary extensions or loading a code from a Gist1.

I had to build my own.

The Plan

  1. load and run gists by visiting URLs in this form: http://ju-jist.herokuapp.com/USER/GIST_ID/FILE_NAME
  2. eventually add a home page that will build the right url from the GIST_ID defaulting to index.html as file name

Section 1: Rack Proxy

The first thing I did is to preparing a simple proxy rack application that would extract the gist id and
file name from the URL:

parts = %r{^/(?<user>[^/]+)/?(?<gist_id>w+)/(?<file>.*)(?:$|?(?<query>.*$))}.match(env['PATH_INFO'])
gist_id = parts[:gist_id]
file = parts[:file]
user = parts[:user]

Note here how handy are actually named Regexp groups (introduced in Ruby 1.9).

Then let’s be ol’ school and use open-uri to fetch urls:

contents = open("https://gist.githubusercontent.com/#{user}/#{gist_id}/raw/#{file}")

Pass it over to Rack:

[200, {}, [contents.read]]

And wrap everything in a rack app:

# config.ru
def call(env)
  parts = %r{^/(?<user>[^/]+)/?(?<gist_id>w+)/(?<file>.*)(?:$|?(?<query>.*$))}.match(env['PATH_INFO'])
  gist_id = parts[:gist_id]
  file = parts[:file]
  user = parts[:user]
  contents = open("https://gist.githubusercontent.com/#{user}/#{gist_id}/raw/#{file}")
  [200, {}, [contents.read]]
end

run self

Section 2: The URL builder

Next I prepared a simple form:

<!-- inside index.html -->
<form>
  <input type="text" id="user_and_gist_id">
  <input type="submit" value="open">
</form>

And then I used Opal and Native with some vanilla DOM to build the URL and
redirect the user.

# gist-runner.rb
$doc  = $$[:document]
input = $doc.querySelector('input#user_and_gist_id')
form  = $doc.querySelector('form')

form[:onsubmit] = -> submit {
  Native(submit).preventDefault
  user_and_gist_id = input[:value]
  $$[:location][:href] = "/#{user_and_gist_id}/index.html"
}

And let Rack serve static files:

use Rack::Static, urls: %w[/gist-runner.rb /favicon.ico], index: 'index.html'
run self

Conclusion

Ju-Jist is up and running, you can see the code from the last article gist live on ju-jist.

The code is available on GitHub.


  1. Actually JSFiddle has some docs for loading Gists, but I wasn’t able to make it work. CodePen and others allow for external resources, but GitHub blocks the sourcing of raw contents from Gists