Book Image

Meteor Design Patterns

By : Marcelo Reyna
Book Image

Meteor Design Patterns

By: Marcelo Reyna

Overview of this book

Table of Contents (13 chapters)

CoffeeScript for Meteor


CoffeeScript is a compiler for JavaScript that adds "syntactic sugar" inspired by Ruby, Python, and Haskell; it effectively makes the writing of JavaScript easier and more readable. CoffeeScript simplifies the syntax of functions, objects, arrays, logical statements, binding, managing scope, and much more. All CoffeeScript files are saved with a .coffee extension. We will cover functions, objects, logical statements, and bindings as these are some of the most commonly used features.

Objects and arrays

CoffeeScript gets rid of curly braces ({}), semicolons (;), and commas (,). This alone saves you from repeating unnecessary strokes on the keyboard. Instead, CoffeeScript emphasizes on the proper use of tabbing. Tabbing will not only make your code more readable, but it will be a key factor in making the code work as well. In fact, you are probably already tabbing the right way! Let's look at some examples:

#COFFEESCRIPT
toolbox =
  hammer:true
  flashlight:false

Tip

Downloading the example code

You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Here, we are creating an object named toolbox that contains two keys: hammer and flashlight. The equivalent in JavaScript will be this:

//JAVASCRIPT - OUTPUT
var toolbox = {
  hammer:true,
  flashlight:false
};

Much easier! As you can see, we have to tab to indicate that both the hammer and flashlight properties are a part of toolbox. The var word is not allowed in CoffeeScript because CoffeeScript automatically applies it for you. Let's have a look at how we would make an array:

#COFFEESCRIPT
drill_bits = [
  "1/16 in"
  "5/64 in"
  "3/32 in"
  "7/64 in"
]

//JAVASCRIPT – OUTPUT
var drill_bits;
drill_bits = ["1/16 in","5/64 in","3/32 in","7/64 in"];

Here, we can see that we don't need to have any commas, but we do need to have brackets to determine that this is an array.

Logical statements and operators

CoffeeScript removes a lot of parenthesis (()) in logical statements and functions as well. This makes the logic of the code much easier to understand at first glance. Let's look at an example:

#COFFEESCRIPT
rating = "excellent" if five_star_rating

//JAVASCRIPT – OUTPUT
var rating;

if(five_star_rating){
  rating = "excellent";
}

In this example, we can clearly see that CoffeeScript is easier to read and write. CoffeeScript effectively replaces the entire implied parenthesis in any logical statement.

Operators such as &&, ||, and !== are replaced by words to make the code more readable. Here is a list of the operators that you will be using the most:

CoffeeScript

JavaScript

is

===

isnt

!==

not

!

and

&&

or

||

true, yes, on

true

false, no, off

false

@, this

this

Let's look at a slightly more complex logical statement and see how it is compiled:

#COFFEESCRIPT
# Suppose that "this" is an object that represents a person and their physical properties

if @eye_color is "green"
  retina_scan = "passed"
else
  retina_scan = "failed"

//JAVASCRIPT - OUTPUT
if(this.eye_color === "green"){
  retina_scan = "passed";
} else {
  retina_scan = "failed";
}

Notice how the context of this is passed to the @ symbol without the need for a period, making @eye_color equal to this.eye_color.

Functions

A JavaScript function is a block of code designed to perform a particular task. JavaScript has a couple of ways of creating functions that are simplified in CoffeeScript. They look like this:

//JAVASCRIPT
//Save an anonymous function onto a variable
var hello_world = function(){
  console.log("Hello World!");
}

//Declare a function
function hello_world(){
  console.log("Hello World!");
}

CoffeeScript uses -> instead of the function() keyword. The following example outputs a hello_world function:

#COFFEESCRIPT
#Create a function
hello_world = ->
  console.log "Hello World!"

//JAVASCRIPT - OUTPUT
var hello_world;
hello_world = function(){
  return console.log("Hello World!");
}

Once again, we will use a tab to specify the contents of the function so that there is no need for curly braces ({}). This means that you have to make sure that you have the entire logic of the function tabbed under its namespace.

What about our parameters? We can use (p1,p2) -> where p1 and p2 are parameters. Let's make our hello_world function output our name:

#COFFEESCRIPT
hello_world = (name) ->
  console.log "Hello #{name}"

//JAVSCRIPT – OUTPUT
var hello_world;
hello_world = function(name) {
  return console.log("Hello " + name);
}

In this example, we can see how parameters are placed inside parentheses. We are also doing string interpolation. CoffeeScript allows the programmer to easily add logic to a string by escaping the string with #{}. Also notice that, unlike JavaScript, you do not have to return anything at the end of the function, CoffeeScript automatically returns the output of the last command.

Binding

In Meteor, we will often find ourselves using the properties of this within nested functions and callbacks. Function binding is very useful for these types of cases and helps to avoid saving data in additional variables. Function binding sets the value of the this object inside the function to the value of this outside the function. Let's look at an example:

#COFFEESCRIPT
# Let's make the context of this equal to our toolbox object
# this =
#   hammer:true
#   flashlight:false

# Run a method with a callback
Meteor.call "use_hammer", ->
  console.log this

In this case, the this object will return a top-level object such as the browser window. This is not useful at all. Let's bind this now:

#COFFEESCRIPT
# Let's make the context of this equal to our toolbox object
# this =
#   hammer:true
#   flashlight:false

# Run a method with a callback
Meteor.call "use_hammer", =>
  console.log this

The key difference is the use of => instead of the expected -> to define the function. Using => will make the callback's this object equal to the context of the executing function. The resulting compiled script is as follows:

//JAVASCRIPT
Meteor.call("use_hammer", (function(_this) {
  return function() {
    return Console.log(_this);
  };
})(this));

CoffeeScript will improve your coding quality and speed. Still, CoffeeScript is not flawless. When you start combining functions with nested arrays, things can get complex and difficult to read, especially when the functions are constructed with multiple parameters. Let's look at a common query that does not look as readable as you would expect it to be:

#COFFEESCRIPT
People.update
  sibling:
    $in:["bob","bill"]
,
  limit:1
  ->
    console.log "success!"

This collection query is passing three parameters: the filter object, the options object, and the callback function. To differentiate between the first two objects, we had to place a comma at the same level as the function and then, indent the second parameter. This is unwieldy, but we can use variables in order to make the query more readable:

#COFFEESCRIPT
filter =
  sibling:
    $in:["bob","bill"]
options =
  limit:1
People.update filter, options, ->
  console.log "success!"

Go to coffeescript.org and play around with the language by clicking on the "try coffeescript" link.