Compile a RequireJS Project to a Single File

Splitting all your JavaScript code into modules and loading them with RequireJS makes for a warm and fuzzy development experience. At some point though, I'd like to deliver a single file with all the dependencies included. The biggest reason being that HTTP requests are expensive and by lazy-loading all your tiny modules, RequireJS makes a lot of them.

There's an optimizing tool for RequireJS called r.js. You can use it to minimize and concatenate your code. The documentation is in a few places and I had a bit of trouble getting it to do what I want. IMHO the best source of info after the basic stuff is the example build file with all the options explained. For installation instructions just check out the documentation.

In this tutorial I'm going to walk you through my build file with a few added comments. Except for a few dirs omitted for brevity, my project structure looks like this:

├── README.md
├── app
│   ├── libs
│   ├── main.js
│   ├── models
│   ├── require.js
│   ├── templates
│   └── views
├── build.js
└── package.json

All the code is in app and external dependencies are in app/libs. The build.js file looks like this.

({
  baseUrl: 'app',
  out: 'build/main.js',

Your paths will be relative to the baseUrl so it makes sense to make this the app folder as all the files there. Specifying the out parameter tells r.js that you want everything in one file. The alternative is specifying dir in which case the contents of your app folder are copied into that dir.

A few options like appDir, dir and modules are incompatible with out aka compiling to a single file so don't use those.

  include: ['libs/almond', 'main'],
  wrap: true,

Usually, you would use the name parameter to specify your main module but we're using include here because we're bundling the almond loader as well. Almond is a much smaller and simpler AMD loader that makes sense in our case because we're not loading modules dynamically.

The include parameter is an array specifying which other modules to include in the build. When we specify the "main" one, r.js traces all other modules that main depends on and includes them.

Wrap, unsurprisingly wraps module requires into a closure so that only what you export gets into the global environment. To be honest, I don't really need this but if you're bundling a widget or something someone will use with a lot of other stuff I guess it's a good idea.

  exclude: ['coffee-script'],
  stubModules: ['cs'],

I use CoffeScript for development and compile files in the browser. This is obviously slower than it needs to be for production so we exclude the compiler module and "stub out" the cs loader plugin. This results in all coffee files being compiled to JavaScript and inlined.

  paths: {
    backbone: 'libs/backbone-amd',
    underscore: 'libs/underscore-amd',
    jquery: 'libs/jquery',
    cs: 'libs/cs',
    'coffee-script': 'libs/coffee-script',
    text: 'libs/text'
  }
})

The rest of the file is a standard paths configuration.

Finally to compile, run:

r.js -o build.js

And your compiled project should be in build/main.js.

A sincere thank you to James Burke for reviewing this post.


Functional Programming in the Small

This bit of helper code came up in a Semaphore code review:

def branch_options_for_select
  urls = []

  if @project.branches.empty?
    urls << ["No Branches", ""]
  else
    @project.branches.each do |branch|
      urls << [branch.name, url_for_branch_status(branch)]
    end
  end

  urls
end

It's written in an unnecessarily imperative style. The first thing that irked me is that it's setting up an empty array and returning it at the end. You can avoid that by using Object#tap like this:

def branch_options_for_select
  [].tap do |urls|
    if @project.branches.empty?
      urls << ["No Branches", ""]
    else
      @project.branches.each do |branch|
        urls << [branch.name, url_for_branch_status(branch)]
      end
    end
  end
end

Tap is an implementation of the K combinator in Ruby. It yields the receiver to a block and returns it when the block returns. We use the block to add elements to the empty array and when the block returns it yields the mutated array.

Since we have two cases, mutating the array seems unnecessary:

  1. For every branch we return an array pair of branch name and url
  2. There are no branches and we just return an array with a pair "No Branches" and an empty string for the url

We can write this method in a more declarative way:

def branch_options_for_select
  if @project.branches.empty?
    [["No Branches", ""]]
  else
    @project.branches.map { |branch| [branch.name, url_for_branch_status(branch)] }
  end
end

Map is a higher order function that applies a function to every element of an enumerable, in this case an array, and returns a new array with the values the function evaluates to.

This method also relies on the @projects variable. If it's not there or if it's named differently, the helper becomes useless. The last part of the refactoring is parametrizing the helper:

def branch_options_for_select(branches)
  if branches.empty?
    [["No Branches", ""]]
  else
    branches.map { |branch| [branch.name, url_for_branch_status(branch)] }
  end
end

While I'm sure someone could code-golf it some more, the idea is to make methods and helpers more declarative, closer to what you would write in Haskell or Clojure. I should mention that the above helper function is not pure since we're using url helpers and they could change if we change our route structure.

But this is close enough for a Rails view helper.


Ego

I wish as a programmer I lived and worked closer to the rules in this list. It's hard to do because it means not letting your emotions and your ego rule how you behave and interact with people you work with. Maybe we occasionally need to be reminded to be mindful of ourselves and others by a story like this one:

Dad and the Ten Commandments of Egoless Programming.


Put Callback Logic Into Callback Objects

I've recently needed to generate a unique hash id for every new record in the database. The usual way I would do it would be by defining methods on a model and passing a method symbol to before_validation like this:

# app/models/request.rb
class Request < ActiveRecord::Base
  before_validation :generate_hash_id, :on => :create

  def generate_hash_id
    hash_id = SecureRandom.hex(12) until has_unique_hash_id?
  end

  def has_unique_hash_id?
    exists?(:hash_id => hash_id)
  end
end

That may look alright but I'd rather have just the unavoidable logic in my ActiveRecord models. One reason being that I'd like my tests to be fast and the other is that I'm probably going to use this generator on a different model so I'm probably better off reusing this.

Rails callbacks can take a method, an object or a Proc. The idea here is to create a callback object and move all the logic there. Your callback object should have a method with the same name as the callback and take a record as a parameter. Here's what it looks like.

# app/models/request.rb
class Request < ActiveRecord::Base
  before_validation HashGenerator.new(self), :on => :create
end

Pretty barren. Let's look at HashGenerator.

# app/callbacks/hash_generator.rb
require 'securerandom'

class HashGenerator
  def initialize(model, opts={})
    @model  = model
    @field  = opts['db_field']  || "hash_id"
    @length = opts['length']    || 12
    @hash   = generate_hash
  end

  def before_validation(record)
    # this doesn't scale very well but let's ignore it for now
    @hash = generate_hash until hash_unique?
    record.send(@field+"=", @hash)
  end

  private

  def generate_hash
    SecureRandom.hex(@length)
  end

  def hash_unique?
    !@model.exists?(@field => @hash)
  end
end

While I don't need it right away, I made the hash length and the underlying db_field changeable with an options hash.

The way I see it, this way you have a lot less logic in your ActiveRecord model. A lovely side-effect is that your logic is now in a plain Ruby object and your spec doesn't need to require spec_helper. Your specs for this functionality run superfast.

I think I'll be creating callback objects for most callbacks. It seems like a really cheap way to thin out models even more.

The only bad thing I see is that there's a bit more code, but I can live with that.

Hacker News thread for comments →


My Short Trip to India

The short part is a bit tongue in cheek since to most people 25 days sounds like a long trip but for India, it's just too short.

Everyone I've met that has been to India has had a unique experience. I went with a couple of my close friends, my best friend already there for three months, finishing his internship. We landed in Bangalore and planned to fly back from Delhi.

India is the first place where I've experienced the feeling of almost too much freedom. You feel a certain connectedness with nature. Partly because animals freely roam through the streets, even in very urban places like Mumbai, and in part because you see an incredibly diverse and almost untouched, nature. Hampi, which is my favourite place of all I've visited, is like that. Like God made a bouldering place for for himself. If you climb, you must visit it.

Me in Hampi.

But India is a land of contrasts as everyone will tell you. You see the extremely poor people and the extremely rich not more than two blocks from each other. Some of the former you can see living in slums and the latter in fort-like mansions. In spite of that, it seemed to me that the (not so rich) people in India are really happy. We had a running joke if were going to stumble upon anyone who'll treat us badly. But now that I think about it, a woman in Jaipur carrying bamboo sticks pulled out the largest knife I've seen when I tried to photograph her.

Indians work a lot. Much more so than people in Serbia or elsewhere I've been. So many people work Sundays that you just don't care which day it is anymore. I tried to get my films developed on Sunday, January first, but the guy in the neighbouring shop told me that the photo store is closed on Sundays. Working on January first was the usual deal for him. It's not that it's mandated that you should be open, it's that by being open you get to earn money that day.

A boy running a masala chai stand in Pushkar.

It seemed to me that there's a kind of entrepreneurial spirit everywhere. Something is happening all the time around you. People are offering you things, fixing things, painting their shopfronts or otherwise making their shop more noticeable in streets packed with small shops. In a Mumbai bookshop you can see a lot of REWORK copies and that 'The Lean Startup' is currently one of the best selling titles.

There's a feeling that there is a free market system in effect on the street level. You go to a rickshaw driver and haggle over the price and sometimes you get to pay less than the meter and sometimes you pay more. I've heard that Indians get offended if you don't haggle, but to me they seemed very happy to see you pay much more than you should. And why wouldn't you do it when it's so much fun.

I really miss India.


Sucking Less at Writing Cucumber

I wrote my first Cucumber scenario about five months ago. It went something like this:

Scenario: Changing email
  Given I am logged in
  And I am on the homepage
  When I click on "Account"
  And I fill in "email" with "milos@example.com"
  And I press "Change Email"
  Then I should see "Email successfully changed"
  When I visit "My profile page"
  Then I should see "milos@example.com"

Maybe my naivete was not solely to blame; I was told it was so easy "that it could be taught to a secretary". I am not so sure anymore.

Some of the problems with the above scenario are:

  • It's too long and verbose
  • It's not using the domain language

Read the scenario. As a reader, why do I need to have a mental model of that web site to be able to follow it? Couldn't it be replaced with:

Background:
  Given I am logged in
Scenario: Changing Email
  Given I am on my account page
  When I change my email
  Then I should see that my email has changed

Using web steps makes you write very imperative scenarios that you have to rewrite each time you change something. It's actually one of the reasons why they were removed from the latest version of cucumber. People used them too much and wrote shitty scenarios. I'm not sure I agree with the descision to completely remove them but I can undestand. The pull request now serves as an explicit note that you should be writing declarative steps.

A good indicator that your scenario is not good is if you change something in your implementation and you have to change the scenario. You'll probably need to change your step definition anyway but the Gherkin stuff should be as decoupled from the implementation as possible. In the above scenario:

  1. How I change my email is an implementation detail and belongs in the step definition
  2. How I see that my email really changed is also an implementation detail

We still test if this whole system works but if I change how it works I only need to change the step definitions. The scenario stays the same.

Lately I just write the whole scenario and implement the steps. I only reuse steps if I see that the one I had just written is similar in wording to some step I had written before. The added benefit of this is that I now know capybara much more intimately than before. Capybara is very powerful and much nicer to work with than web steps.


Apprenticing at Rendered Text

I've kinda fell in love with Ruby after several love affairs with different languages. Somehow it just felt right both for reading and for writing. So I've set out on a mission to write a lot of Ruby code over the summer. Luckily, the guys from Rendered Text needed help of an eager new rubyist and I needed a place to work with Ruby so that I can "get it into my fingers". I was really excited because I knew they weren't locked in into some old legacy software system but were open to whatever works, new or old. I also knew they were into software crafstmanship which is a movement in software development that I really like.

Me at Rendered Text

Since I live in Belgrade and the Rendered Text office is in Novi Sad, the deal was for me to work remotely and occasionally go to Novi Sad for a few days. I had my first week in Novi Sad, mostly pairing with Darko.

Pairing

In the first week, I paired with Darko on some Ruby code. I was happy that it was pure Ruby and not Rails because at the time my Rails knowledge was rather weak. I've only just read The Ruby on Rails Tutorial book and I thought that I would be useless as a pilot or copilot. That turned out to be wrong and I was surprised to actually be useful. Maybe if it were Rails code I would have done worse, but probably not that much worse. Even if you don't know the code, you're still useful in a pair programming session because you review code and ask questions about it as it is written.

Pairing is also a great way to pick up editor and workflow tricks. I know I've picked up quite a bit of vim and git tricks from Darko. I think he got a few from me as well.

Code reviews

We use GitHub's pull request feature quite a bit. Most of the time when I wrote a piece of code that isn't trivial, I would open a pull request and either Marko or Darko would review it. This is by far where I learned the most. Writing some code the way I think it should be done and then getting detailed feedback on how it can be done better is invaluable.

Review

Reading

Before I even started I needed to get up to speed with the tools used at Rendered Text, mainly RSpec, Cucumber and Rails. Marko and Darko suggested The RSpec book and The Ruby on Rails Tutorial. To this I would add Apprenticeship Patterns. I probably should have read it earlier in my apprenticeship.

I wanted to read as many books, articles and blog posts as I could, but there's only so much you can read in two months. It's great to be able to discuss what you read right away with people who have way more real world experience. Especially as I got interested in object-oriented design. I would come in and try stuff I read about in a blog post or a book and could get feedback or even a discussion going.

BDD

Pretty much everything done at Rendered Text is developed using Behaviour-Driven Development. I was already sold on TDD before I arrived but I needed to acquire a taste for writing acceptance tests with Cucumber. At first I really sucked at this. It was hard for me to write good scenarios. Fast forward a few months, I still suck at it but a little bit less. An area to improve I guess. Reading the RSpec Book's chapters on Cucumber helped. I'm planning to read through the new Cucumber Book, and I hope that'll help as well.

Working remotely

While it was super nice to work at the Rendered Text office, most of my work time was spent at home. We use Campfire quite a bit and also Pivotal Tracker and Basecamp. Campfire is super cool, kind of like irc on steroids.

Tools aside, working remotely has some benefits but also some not so trivial downsides. The biggest benefit is that you don't have to commute to work. The biggest downside is that it's sometimes much harder to "get in the zone". Pomodoros can help with this.

What I did wrong

I think the biggest mistake I made was not reporting that I was stuck soon enough. Several times when I couldn't do something that I assumed was simple and that I could "figure out", it turned out to be far from reality. I would spend a lot of time without anything to show for it. To make matters worse, it was usually something that would take a few lines on Campfire to resolve. In hindsight I really should have asked for help as soon as I got stuck. Asking on Campfire isn't as attention stealing like tapping someone on the shoulder and If someone knows it, you usually get an answer pretty quickly. If it turns out you can figure it out yourself, you just update the Campfire channel and there's way less time wasted.

Conclusion

This was so far the nicest part of my working life. I've learned a lot, had quite a bit of fun and met really nice people. I'm also very happy that I'll continue to work for Rendered Text.

To any aspiring software crafsmen, I cannot recommend apprenticing highly enough.

As seen on the Rendered Text blog.


Radiance Color-Theme for Emacs

I've created a color-theme that should integrate nicely into a desktop using Ubuntu's Radiance theme.

I think it looks pretty neat. Below is a screenshot with the code for the theme in an Emacs buffer.

You can get it from its GitHub repository. Contributions are very much welcome. If your language of choice doesn't look good, please create an issue or send me a pull request.


Redesigned, Again

I think it's probably better that I don't write design details of my blog. I like to fiddle with the looks and it will make some of my posts outdated too fast.

Currently I'm using League Gothic for headers, Lucida Grande for body text and Monaco for code. If you haven't got those two, you get to see similarly paired fonts for your system.


How I set up my Blog

I've decided to keep a blog to remind myself of the things I'm doing and learning. Someone else might also benefit from that as well. Since I've become somewhat of a Ruby enthusiast, I decided to use Jekyll.

What is Jekyll?

Jekyll is a static site generator written in Ruby by Tom Preston-Werner(of GitHub fame). You create a set of templates and then just write your posts in plain text using your markup of choice(I use Markdown). Jekyll then transforms everything into static HTML that can be served by pretty much anything you like.

The nice thing about everything being plain text is that I can use Emacs to write posts. It has a very nice markdown-mode. I use Git to push everything into a GitHub repository so I backup both my code and my content. You are free to browse everything here

Design

My goal was to have a clean design that makes it pleasant to read what I write. I use Calluna Sans served by typekit. Calluna Sans is a very nice humanist sans-serif typeface made by Jos Buivegna. You should definitely check out his other fonts. Code is, or rather will be, typeset in Inconsolata. Everything follows a vertical rhythm which I think looks very pleasing.

If you're using Firefox 4, you can see some advanced typographical features such as small caps and ligatures turned on here and there.

If you have comments of any kind, I would be glad to hear from you.