Skip to content
Dave Strus edited this page Nov 18, 2014 · 1 revision

CoffeeScript

Rails includes CoffeeScript by default. CoffeeScript is a language that compiles into JavaScript.

From coffeescript.org:

Underneath that awkward Java-esque patina, JavaScript has always had a gorgeous heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.

The golden rule of CoffeeScript is: "It's just JavaScript". The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. You can use any existing JavaScript library seamlessly from CoffeeScript (and vice-versa). The compiled output is readable and pretty-printed, will work in every JavaScript runtime, and tends to run as fast or faster than the equivalent handwritten JavaScript.

We could rewrite our existing JavaScript in CoffeeScript as follows:

$ ->
  $("#notes > li").click (ev) ->
    ev.preventDefault()
    location.href = $(this).data("url")
  $(window).resize(->
    $("#sidebar").height $(window).height() - 55
    $(".bootsy_text_area").height $(window).height() - 210
  ).trigger "resize"

(This is not the 100% equivalent CoffeeScript, as the return values of our functions would be a different. Given that we weren't using the return values, it doesn't really matter.)

A couple of differences are immediately apparent:

  • Functions are defined using Ruby-like lambda syntax.
  • Parentheses are optional on function calls unless they are needed to eliminate ambiguity.

On that second point, it's interesting to note that the parentheses are always needed when calling a function without passing any arguments. Without the parentheses, CoffeeScript doesn't know whether you mean to call the function, or simply reference that function. The function is an object itself, after all.

That simple rewrite of our JavaScript may not seem like it gains us much. We do a more interesting rewrite using CoffeeScript's class structure, which takes some of the pain out of using JavaScripts prototypal object-oriented nature.

app/assets/javascripts/notes.js

class Note
  constructor: ->
    @handleClicks()
    @resizeElements()

  handleClicks: ->
    $('#notes > li').click (ev) ->
      ev.preventDefault()
      location.href = $(this).data 'url'

  resizeElements: ->
    $(window).resize( ->
      $('#sidebar').height $(window).height() - 55
      $('.bootsy_text_area').height $(window).height() - 210
    ).trigger 'resize'

window.Note = Note

$ ->
  new Note()

That CoffeeScript compiles to the following JavaScript:

var Note;

Note = (function() {
  function Note() {
    this.handleClicks();
    this.resizeElements();
  }

  Note.prototype.handleClicks = function() {
    return $('#notes > li').click(function(ev) {
      ev.preventDefault();
      return location.href = $(this).data('url');
    });
  };

  Note.prototype.resizeElements = function() {
    return $(window).resize(function() {
      $('#sidebar').height($(window).height() - 55);
      return $('.bootsy_text_area').height($(window).height() - 210);
    }).trigger('resize');
  };

  return Note;

})();

window.Note = Note;

$(function() {
  return new Note();
});

With relatively simple JavaScript like we started with, we don't really get to show off CoffeeScript's biggest benefits. If you would like to use the CoffeeScript version in your project, rename notes.js to notes.js.coffee and use the CoffeeScript code in place of the original JavaScript.