Doing like a module with Rails asset-pipeline and CoffeeScript

Some days ago, I played around with requirejs. Although I liked to group my client side code into AMD modules, using the (only) appropriate gem ‘requirejs-rails’ doesn’t felt that good. Main reasons for that

  • last commit some months ago
  • no Rails 4 support so far
  • asset precompilation failed with my concrete project

To be fair, that asset:precompile issues with requirejs-rails were caused by some third-party Gems I used. But anyway, they compiled under stock Rails and they failed when using requirejs-rails. So it seems that sprockets integration isn’t that flawless with requirejs-rails.

So I thought about how to get some module-like-feeling, with just the tools, Rails delivers out of the box. Let’s approach.


Let’s assume the following class hierarchy

  SeatPlan < Component

SeatPlan should be a subclass of Component. Also I wanted InputDataSanitzer to be a class on its own, but located “below” SeatPlan, because it only sanitizes SeatPlan input data. Think of some kind of namespacing. Same for Ui. The only difference between these two is, that SeatPlan should store a reference to DataInputSanitizer, where as for Ui it should only store a concrete instance.


With AMD, I would write something like this

# assets/javascript/
define ->
methodEverybodyShouldHave: ->
# assets/javascript/SeatPlan/
define ->
sanitize: (data) ->
# assets/javascript/SeatPlan/
define ->
constructor: (el) ->
# assets/javascript/
define ['Component', 'SeatPlan/InputDataSanitizer', 'SeatPlan/Ui'], (Component, InputDataSanitizer, Ui) ->
class extends Component
constructor: (el)
@InputDataSanitizer = InputDataSanitizer
@ui = new Ui(el)

Imitate AMD with sprockets

Without something like AMD, you have to put these classes somewhere in global scope in order to access them from within your client-side code. Let’s put them below

  + app
    + Component
    + SeatPlan
      + InputDataSanitizer
      + Ui

Combining Rails asset-pipeline directives and some CoffeeScript we can imitate something like a module system. Let’s look at the code.
Thanks to CoffeeScripts ‘do’, which allows us to explicitly create a closure, it feels almost like doing AMD. Just without the need for any additional Gem/module loader.

Doing like a module with Rails asset-pipeline and CoffeeScript

Include files from git submodules when building a ruby gem

Today I ran into the following situation. I wanted to build a gem with bundler which has some vendor assets included as git submodules. My directory structure was something like that

vendor/assets/javascripts/es5-shim (submodule)
vendor/assets/javascripts/pathjs (submodule)

When doing

rake build

the files from the submodules where not included in the gem, because the gemspec specifies the files as follows.

gem.files = `git ls-files`.split($\)

Unfortunately, git ls-files does not list files from submodules and that’s why, these files are not included in the gem.

I solved this by utilizing git submodules’s foreach statement in combination with some ruby string manipulation.

The resulting gemspec looks like this.

# -*- encoding: utf-8 -*-
require File.expand_path('../lib/example/version', __FILE__) do |gem|
gem.authors = ["John Doe"] = [""]
gem.description = %q{Write a gem description}
gem.summary = %q{Write a gem summary}
gem.homepage = ""
gem.files = `git ls-files`.split($\)
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) = "example"
gem.require_paths = ["lib"]
gem.version = Example::VERSION
# get an array of submodule dirs by executing 'pwd' inside each submodule
`git submodule –quiet foreach pwd`.split($\).each do |submodule_path|
# for each submodule, change working directory to that submodule
Dir.chdir(submodule_path) do
# issue git ls-files in submodule's directory
submodule_files = `git ls-files`.split($\)
# prepend the submodule path to create absolute file paths
submodule_files_fullpaths = do |filename|
# remove leading path parts to get paths relative to the gem's root dir
# (this assumes, that the gemspec resides in the gem's root dir)
submodule_files_paths = do |filename|
filename.gsub "#{File.dirname(__FILE__)}/", ""
# add relative paths to gem.files
gem.files += submodule_files_paths

view raw


hosted with ❤ by GitHub

Matt Connolly suggested a shorter version of the gemspec. Have a look at his comment.

Include files from git submodules when building a ruby gem