A Better $patch Method for Angular’s ngResource

Angular’s ngResource makes a pretty decent starting point for developing a front-end model layer, but tends to be a little simplistic as your backend API gets more sophisticated.

One issue I ran into recently is that the $patch method sends the entire object in the request body. This is usually not what you want to do, because the PATCH method is designed for a partial resource modification, typically using something like JSON Merge Patch or JSON Patch as the request body.

Here’s how to add a $patchFields method to your resource that creates a JSON Merge Patch for a set of fields, and then sends it to the backend.

This is how you’d use it:


var product = new Product({ id: 231 name: 'iPad', price: 429.99, size: { height: 9.4, width: 6.2, depth: 0.2 } }); product.price = 400; product.size.height = 10; var promise = product.$patchFields(['price', 'size.height']); /* * Sends a request like this: * PATCH http://api.example.com/products/231 * { * "price": 400, * "size": { * "height": 10 * } * } * */

And here’s the code:

angular.module('myApp').factory('Product', function($resource) {

   var Product = $resource('http://api.example.com/products/:id', { id: 'id' });

   angular.extend(Product.prototype, {
      '$patchFields': function(fields, success, error) {
         var self = this;
         patch = self.generatePatch(fields);
         var result = Product.patch.call(this, { id: self.id }, patch, success, error);
         return result.$promise || result;
      },
      generatePatch: function(fields) {
         var self = this;
         if(!angular.isArray(fields)) {
            fields = [ fields ];
         }

         return fields.reduce(function(result, fields) {
            setFieldByPath(result, field, self.getFieldByPath(field));
            return result;
         }, {});
      },
      getFieldByPath: function(path) {
         var ret = angular.toJson(json);
         var paths = path.split('.');
         for(var i = 0; i < paths.length; ++i) {
            if(angular.isUndefined(ret[paths[i]])) {
               return undefined;
            } else {
               ret = ret[paths[i]];
            }
         }
         return ret;
      }
   });

   function setFieldByPath(obj, path, value) {
      var paths = path.split('.');
      vat setOn = obj;

      for(var i = 0; i < paths.length - 1; i++) {
         if(!angular.isUndefined(setOn[paths[i]])) {
            if(angular.isObject(setOn[paths[i]]) && !angular.isArray(setOn[paths[i]])) {
               setOn = setOn[paths[i]];
            } else {
               throw new Error('Path ' + path + ' has an item that is not an object');
            }
         } else {
            setOn[paths[i]] = {};
            setOn = setOn[paths[i]];
         }
      }

      if(!angular.isFunction(setOn[paths[paths.length - 1]])) {
         setOn[paths[paths.length - 1]] = value;
      } else {
         throw new Error('Cannot set value at ' + path + ' since it would overwrite a function');
      }
   }

   return Product;

});

Using Jupyter for Exploring a Heroku Database

If you want to establish a connection to a Heroku database and import data into Jupyter for some analysis, here’s some boilerplate to help:

# Python 3
from sqlalchemy import create_engine
import pandas as pd
import subprocess

DATABASE_URL = subprocess.check_output("heroku config:get DATABASE_URL --app <your heroku app name here>", shell=True).decode('utf-8')
engine = create_engine(DATABASE_URL)

result = pd.read_sql_query(
    '''
SELECT * FROM my_table;
    ''',
    con=engine)

Now you have result, which is a Pandas DataFrame. Happy data exploration!

Note: It probably goes without saying this is a bad idea to do on a production system. You should use a read-only replica for running queries in production, or use a dump of the database loaded onto another server.

Draft.js Data Model Demo

Facebook released a very interesting React-based rich text editor called Draft.js. The advantage of something like is that you have much more control over the data model for structured documents.

The documentation is a little sparse on examples of what the underlying data model looks like, so I build this quick demo that renders the data model in JSON.

See it live here.

Draft.js Data Model Demo Screenshot
Draft.js Data Model Demo

Getting Jetbrains DataGrip to work with Heroku Postgres

Heroku Postgres forces you to use SSL, but the connection isn’t signed with a well-known CA. To get this to work in DataGrip, you have to mess around with some JDBC settings. Here’s how to do it:

In the add connections dialog, enter the username, password, hostname, port, and database name. You’ll have to enter these manually, because DataGrip’s URL support only works with JDBC database URLs, not the more common Postgres URLs used by Heroku.

Next, click on the Advanced tab. Then find the ssl property and set it to true. Then find the sslfactory property and set it to org.postgresql.ssl.NonValidatingFactory.

You should be good to go!

Abstract Classes with Static Methods in ES2015

ES2105 classes have much better support for static method patterns than traditional ways of doing it in ES5.

In ES2015, there are actually two prototype chains in classes: one for instance methods and one for static methods. This means you can use super and this in a static method, and it works as expected.

This makes using an abstract class pattern much easier. Here’s an example:

'use strict';

class AbstractShape {
  static get SHAPE_NAME() { throw new Error('must specify a SHAPE_NAME in your subclass of AbstractShape'); }

  static get englishName() {
    return this.SHAPE_NAME['en-US'];
  }

  static get spanishName() {
    return this.SHAPE_NAME['en-MX'];
  }
}

class Square extends AbstractShape {
  static get SHAPE_NAME() {
    return {
      'en-US': 'square',
      'es-MX': 'cuadrado'
    }
  }
}

console.log(Square.englishName); // -> 'square'
console.log(Square.spanishName); // -> 'cuadrado'
console.log(AbstractShape.englishName); // Throws an Error

A few things that are interesting with ES2015 static methods:

  • You can’t have static properties, but you can make static getters to get the same effect (with some syntactic noise).
  • In a static method, this refers to the class itself. Effectively, you can just access other static methods with this.
  • You cannot refer to the class itself in the class body. This is not legal:
static get englishName() { return AbstractShape.SHAPE_NAME['en-US']; }

I’m guessing is the reason for this is that classes are not hoisted in ES2015.

More class posts coming soon!

Refactoring an Existing NodeJS App for ES2015 (Part 1)

Thinking of getting started with ES2015? Coding with NodeJS v5.0.0 or higher? You can get started today! Node supports many features of ES2015 natively, without the need for a transpiler like Babel or Traceur.

ES2015 actually has a lot of really awesome features, and I think most of them are worthwhile to start using eventually. But, it you already have a Node app written and want to introduce ES2015 gradually, which features should you pick first?

This post talks about the three ES2015 features that I would focus on first. I picked these because they are the most compatible with existing patterns and are the easiest for developers to pick up and start using right away. They are also all supported fully in Node 5.x.

The features are:

  1. Block-scoped declarations (let and const)
  2. Arrow functions
  3. Template strings and new String methods

Part 2 will of this series will talk about classes.

Start using block-scoped variable declarations (let and const) instead of var

Note: You need to be in strict mode ('use strict') for these keywords to work. If you are using the Node REPL, you need to start it with node --use_strict as opposed to typing 'use strict'; within the REPL.

What is this let business?

The var keyword has a few issues that have been corrected by the new let keyword. First of all, var may be hoisted like this:

bla = 2; 
var bla;

// is identical to:
var bla;
bla = 2;

Second of all, var-defined variables have the scope of entire enclosing function.

function varExample() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

The let keyword avoids all of this weirdness. When you use let there is no hoisting, so you will get a ReferenceError at runtime:

function a() {
   c = 1;
   let c = 2;
   return c;
}
a(); // ReferenceError: c is not defined

Variables declared with let are block-scoped, not function scoped. A block is any section of code delimited with { ... }. Here’s an example:

let x = 1;
let y = 2;
if (y > x) {
  let a = 3;
  x = a;
}
console.log(x); // 3
console.log(y); // 2
console.log(a); // ReferenceError: a is not defined.

What about const?

The const keyword follows the same scoping and (non-) hoisting rules as let. It has one more constraint, though: variables declared with const don’t change their reference.

Here’s a few examples:

const A = 1;
A = 2;   // TypeError: assignment to a constant variable

It’s also important to realize that const doesn’t enforce immutability for objects. You can change object properties of objects declared with const:

'use strict';
const MY_OBJECT = {
   MyProp: 1
};
MY_OBJECT.MyProp = 2; // no error here!
console.log(MY_OBJECT.MyProp); // 2

Refactoring recommendation

If it is possible to use const, use it. If it isn’t possible to use const, use let. Don’t use var anymore, unless you find some crazy edge-case where it is necessary.

Arrow functions

Arrow functions are a shorthand for writing small, anonymous functions. They also adopt the scope of their surrounding code, rather than creating a new one. This can eliminate use of the var self = this; pattern, and eliminate some uses of .bind().

Arrow functions also have a further-shortened version for implicitly returning the value of an expression. This is great for iterators and lodash-style functional programming.

Here are some examples:

let myArray = [1, 2, 3];
// These are all equivalent:
myArray.map(function(i) { return i + 1; })
myArray.map((i) => { return i + 1; });
myArray.map((i) => { i + 1; });
myArray.map((i) => (i + 1));
myArray.map((i) => i + 1); // expression (i + 1) must be on one line
myArray.map(i => i + 1); // also must be on one line
// all return [2, 3, 4]

Here’s an example of the way this works with arrow functions:

function Person () {
   this.age = 0;
   setInterval(function() { this.age++; }, 1000);
}
let p = new Person();
p.age; // -> 0
// (wait a few seconds)
p.age; // -> still 0

You could fix this with self, but that is annoying. Arrow functions make this easier:

function Person() {
   this.age = 0;
   setInterval(() => { this.age++; }, 1000);
}
let p = new Person();
// (wait a few seconds)
p.age // -> not zero

There are a few other differences with arrow functions that are more obscure:

  • Within the arrow function, arguments refers to the surrounding function, not to the argument list of the arrow function.
  • .call(), .bind(), and .apply() cannot change the scope of an arrow function. They still work otherwise (and have the same function signatures themselves). If you use them, this within the arrow function will just be unchanged.

Refactoring recommendation

Use arrow functions extensively. They are way better. One important thing to note, however, is that you still must use the anonymous-function syntax for method declarations:

let MyClass = BaseClass.extend({ 
   myMethod: function() { 
      return 'the return'; 
   } 
});

Template strings

Template strings are common in other programming languages (Like PHP, Python, and Ruby). They let you avoid code like this, which is extremely prone to errors and typos:

let now = month + ' ' + day + ', ' + year + ' ' + hour + ':' + minute;

With template strings you can write:

let now = `${month} ${day}, ${year} ${hour}:${minute}`;

Template strings start and end with backticks (`). You can put any expression within the templates:

let a = 2;
let myString = `2 plus ${a} is ${2 + a}`;
// -> "2 plus 2 is 4"

Template strings can also be multi-line:

let myString = `This is a
multi-line string`;
// -> "This is a\nmulti-line string"

Refactoring recommendation

Use template strings in most cases where you would normally use string concatenation. Definitely use template strings for multi-line strings. They are particularly useful for inline templates in Angular directives.

New String methods

The String class has a few new useful methods. The most useful ones are:

  • haystack.includes(needle) – tests if a haystack includes needle. No more haystack.indexOf(needle)!
  • haystack.startsWith(needle) and haystack.endsWith(needle) – self explanatory.
  • 'test '.repeat(3) – returns 'test test test '.

Refactoring recommendation

Definitely use these methods instead of indexOf() for checking for substrings. They are much more readable.

How to Create an EEG Spectrogram with Python

I recently got a Neurosky Mindwave, which measures EEG waves and sends them via Bluetooth to your computer or phone.

Busting out some of my rusty signal processing from college, I made a spectrogram from the EEG. Check it out!

EEG Spectrogram
EEG Spectrogram from Mindwave Mobile

To check out how I made this, see this IPython notebook. This is using Jupyter and Python 3, with data recorded using node-thinkgear-sockets.

How to Parse Sketch Files with NodeJS

I’ve recently been working more with Sketch, and wanted to see if I could get Sketch files to render on Linux. Turns out that no one has released open-source software to parse or open Sketch files yet, so I decided to see how hard it would be to parse them with NodeJS.

Here’s the results of my efforts: Github Project

This needs more work to make it usable, but Sketch files aren’t too difficult to deal with.

Two Resources to Learn About Copywriting

  1. The Google Material Design Guidelines for Writing. The whole Material Design style guide is a good read to learn about UX, but the writing section is excellent to learn about writing clear, concise copy for user interface.

  2. Key Questions to Ask Before Writing & Before Testing Advertising Copy. This article has an excellent description of the difference between inductive and deductive writing strategies. When technical experts write, they typically do so in a deductive way, leading the reader through a logic argument that culminates in the conclusion. That might not work well for advertising copy, and this article explains why.