Writing a Sprockets plugin

Sprockets is the thing behing Rails Asset Pipeline. It's a powerful asset processor with many already built-in goodies. It's the thing which takes your assets(be it sass, coffee, etc..) and does all the boring compiling, concatenating, minifiing and compressing. It's also designed to be easily extensible in case you need to integrate something Sprockets don't support out of the box.

Ok, so imagine you'v just discovered some new and shiny frontend thing you want to try. Let's say it's Elm. Now wouldn't it be nice if you could just drop Elm files in you app/assets, let the Asset Pipeline handle the heavy lifting, and just focus on new realtime search in your side project(which is gonna be the next big thing)?

I know it would. And it doesn't take more than 10 minutes. Let's do it from top to bottom:

1) The Initializer


# config/initializers/elm_sprockets_plugin.rb

require 'elm_transformer'

Rails.application.config.after_initialize do |config|
  config.assets.register_mime_type 'text/x-elm', extensions: ['.elm']
  config.assets.register_transformer 'text/x-elm', 'application/javascript', Transformer.new
end

On the first line we tell Sprockets how to recognize Elm files - by theirs '.elm' file extension. On the second line we say what Sprockets should do with them - transform with our custom ElmTransformer processor.

2) The Transformer

The things which process various source files in Sprockets are called simply 'processors'. There are few types of them. The type we need now is 'transformer' - it takes source code in one language(Elm) and outputs it in another(JS).

Processor is anything which responds to `#call` method with one argument. Like this for Elm:


# lib/elm_transformer.rb

require 'elm/compiler'

class ElmTransformer
  def call(input)
    input_file = input[:filename]

    compiled_elm =
      Dir.chdir(Rails.root) do
        ::Elm::Compiler.compile(input_file)
      end

    compiled_elm
  end
end

The compiling itself is done through this gem which you need to include in your Gemfile. You also have to have Elm installed on your system.

3) The View

Now to test it in action, install new Elm package in you Rails root with `elm package install` and create following Elm file:


-- app/assets/javascripts/Main.elm

module Main exposing (..)

import Html exposing (..)

main =
  text "Hi from Elm!"

And lastly in some Rails view:

    <div id="elm-container">
</div>

<script type="text/javascript" charset="utf-8">
  var node = document.getElementById('elm-container');
  var app = Elm.Main.embed(node)
</script>

And this is it! This is all it takes to integrate completelly different language into Rails. Go visit the page and see yourself. Pretty cool for about 20 LOC isn't it?

I build this example app with which you can experiment if you want: https://github.com/Masa331/sprockets_plugin_example_app