Find keys with [null] values.

given:

var account = {  
  owner: {
    firstname: null,
    lastname: 'marley',
    dob: {
      day: 1,
      month: null,
      year: 1950}},
  friends: [{x: null}, 2],
  address: {
    street: undefined,
    city: null,
    state: 'null',
    country: null},
  age: null};

algorithm:

errors = [];  
function findNullKeys (obj, keyString){  
  keyString = keyString || '';
  for( var key in obj ){
    if (obj[key]===null){
      errors.push(keyString===''?key:keyString+'.'+key)}
    else if(typeof obj[key] === 'object' && !Array.isArray(obj[key])){
      findNullKeys(obj[key], keyString===''?key:keyString+'.'+key);}}}

findNullKeys(account);  
console.log(errors);  

result:

[ 'owner.firstname',
  'owner.dob.month',
  'address.city',
  'address.country',
  'age' ]

mem already exists :(

I've been working on a side project called mem. It's a task management tool, so it's related to memory and has as its wicked sick logo the ancient phoenecian letter 'mem'.
mem

The purpose of mem was to overcome the limitations of my todo list of choice–Asana. Asana is great for teams because of its collaboration tools, e.g. assigning, following and commenting on tasks. But it is getting bloated, and is not improvable. (I wrote a Chrome extension to collapse sections, but because Asana periodically re-renders the DOM, it's a real pain to maintain the event listeners.)

Two important concepts Asana lacks are task time estimates and task dependencies. The former is easy enough to overcome, by prepending '10m' or '1h' to a task name, but it's ugly. The latter, where one task blocks another such that the two must be completed in order, is not possible.

I began with high aspirations–an ionic-angular hybrid iOS/web app–and immediately got bogged down in UI concerns. After stepping back, I focused in on the MVP: proving that task estimation and dependecies are useful. To prove that doesn't require a fancy UI; even command line would do! So I rewrote mem as with a CLI.

Paring down to MVP by ditching a 'normal' UI dramatically increased my productivity. Almost immediately, I was able to start using mem to guide its own development by creating tasks of what features to build next. Within a few commits I had add, get, show and tag. A normal workflow looked like this:

$ mem add 'implement requires task dependency'
$ mem add 'eat lunch'
$ mem get 'implement requires task dependency'
$ mem tag meta    
$ mem show
> 0 name:'implement requires task dependency' tags:[meta]
> 1 name:'eat lunch'

Along the way by using mem itself I discovered a bunch of important use patterns, and so implemeted command chaining, tag coloring, and search negation, among other minor features:

$ mem add 'get milk' tag chores tag 'in progress' 
$ mem get 'get milk' examine tags untag 'in progress' tag done
$ mem show ^done

But today I learned about TaskWarrior. It is everything I've built, everything I had planned to build, and it has a community of at least tens of developers working on it or its ecosystem. So now the question to you, dear reader: do I continue with this project as a purely academic exercise, or switch to TaskWarrior and move on? Either way, I've learned lots from designing and building mem, but it's disappointing to think of my work as mere duplication.

Creating Algorithms: Object Diffs

Say we allow users to update account information, but we don't want to keep sending the entire object each time. We need to find the diff of the two objects! Surprisingly this is not part of underscore or lodash, so I decided to write a version of it below.

Here's an approach to developing an algorithm that's equally applicable to work and whiteboarding interviews:

  1. write the steps you want to take in pseudocode:
for each property  
  if it's not in the old object
    add it to result
  else it's in old object
    if it's an array
      continue (maybe handle these later)
    if it's an object
      recurse into it
      if the result object is not empty,
        add to result
    else it's a value
      if it's not in the old object,
        add it to the result
return result  
  1. fill in a line of actual code for each line of pseudocode:
function objDiff(newObj, oldObj){  
  var result = {};
  for(var p in newObj){
  // for each property
    if(!oldObj.hasOwnProperty(p)){
    // if it's not in the old object
      result[p] = newObj[p];
      // add it to result
    } else {
    // else it's in old object
      if(Array.isArray(newObj[p])){
      // if it's an array
        continue;
        // continue (maybe handle these later)
      } else if(typeof newObj[p] === 'object'){
      // if it's an object
        var subResult = objDiff(oldObj[p], newObj[p]);
        // recurse into it
        if(Object.keys(subResult).length){
        // if the result object is not empty,
          result[p] = subResult;
          // add to result
        }
      } else {
      // else it's a value
        if(newObj[p] !== oldObj[p]){
        // if it's not in the old object,
          result[p] = newObj[p];
          // add it to the result
        }
      }
    }
  }
  return result;
  // return result
}
  1. if it's going into production, you should probably uglify and minify it (529 characters to 240):
function objDiff(a,b){var c={};for(var d in a)if(b.hasOwnProperty(d)){if(Array.isArray(a[d]))continue;if("object"==typeof a[d]){var e=objDiff(b[d],a[d]);Object.keys(e).length&&(c[d]=e)}else a[d]!==b[d]&&(c[d]=a[d])}else c[d]=a[d];return c};  
  1. of course, don't forget to test it! (I wrote these tests first so it would be easy to tell when the algorithm works):
var old1 = {firstname:'alice', lastname:'andrews', dob: {day: 01, month: 02, year: 2003}, nest: {hive: {bib:'tum'}}};  
var new1 = {firstname:'alice', lastname:'barkley', nest: {hive: {bib:'tum', bob:'tim'}}, dob: {day: 05, month: 02, year: 2003}, bankAccount: {accountNumber: 123490, routingNumber: 000012}};  
console.log('objDiff:',objDiff(new1, old1));  

Test result:

{
  lastname: 'barkley',
  nest: { hive: { bob: 'tim' } },
  dob: { day: 1 },
  bankAccount: { accountNumber: 123490, routingNumber: 10 }
}

Effective GitHubbing with aliases

So you did that blind $ git add ., and now you're stuck with a bunch of staged files you don't want to commit. How do you undo that again?

Wouldn't it be nice to have shortcuts like these?

$ git unadd [file/folder]
$ git unstage [file/folder]
$ git ignore [file/folder]
$ git hub # open the GitHub repo 

Well now you can!

Run $ git config --global --edit to open your global git configuration in your default editor.

Append these aliases to that file and save it.

[alias]
  unstage="rm -r --cached --"

  unadd="rm -r --cached --"

  hub=!open $(git remote --verbose | grep origin | grep fetch | awk '{print $2}' | sed s/.git$//g | sed s,git@github.com:,https://github.com/,g)

  ignore=!echo >> .gitignore

  echo=!echo $(git remote --verbose | grep origin | grep fetch | awk '{print $2}' | sed s/.git$//g | sed s,git@github.com:,https://github.com/,g | sed s,https://github.com/.*/,,g)

Quick note about $ git echo: I include it here because you can replace echo with a command that takes the repo name as its argument.

Happy gitting!

Automated test coverage (& badge!)

Given how important test coverage is, I was surprised at the lack of complete tutorials for Node.js apps. So here's how to set up istanbul.js and coveralls.io!

  1. I'm assuming you have already set up Travis-CI to run your Karma.js tests with gulp.js.

  2. Sign up for Coveralls.io.

  3. Turn on the repo you want to use, and copy your token. (Keep it secret!)

  4. On your Mac, add the following two environment variables to your ~/.bash_profile ($ open ~/.bash_profile):

export COVERALLS_SERVICE_NAME='travis-ci'  
export COVERALLS_REPO_TOKEN='W0x  your token here  whF'  
  1. Back in your local repo, run $ npm install coveralls karma-coverage gulp-shell --save-dev to install Coveralls, karma-coverage (including istanbul), and gulp-shell so you can run bash with gulp.

  2. Modify your karma.conf.js file to include 'karma-coverage' in plugins, 'coverage' in reporters, and the preproccesors block.

    plugins: [..., 'karma-coverage'],
    reporters: [..., 'coverage'],
    preprocessors: { '!(*spec).js': 'coverage' }, //exclude *spec.js files
    coverageReporter: {
      type: 'lcov',
      dir: 'coverage',
      subdir: '.' // Output the results into ./coverage/
    }
  1. Add the following task to your gulpfile.js:
gulp.task('coveralls', ['karma'], function(){ // 2nd arg is a dependency: 'karma' must be finished first.  
  // Send results of istanbul's test coverage to coveralls.io.
  return gulp.src('gulpfile.js', {read: false}) // You have to give it a file, but you don't have to read it.
    .pipe(shell('cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js'));
});

Running $ gulp coveralls will now look for the coverage/lcov.info file that karma-coverage generates and send it (with your environment variable token) to Coveralls.io for processing.

  1. Add this new 'coveralls' task after your existing 'test' tasks, for example:
gulp.task('test', ['karma', 'coveralls']);  

That's it! Running $ npm test (or $ gulp test, should do the same) should run your karma tests, generate istanbul coverage (which you can check locally with $ open coverage/lcov-report/index.html), and send it to Coveralls.io! The end result is you can log in to Coveralls, see your coverage results, and finally add that fancy badge to your repo's README.md! badge

Optimizing for Developer Time

Your bash profile lets you configure your Terminal.app. You can access it via $ nano ~/.bash_profile (ctrl-x to exit). Here are some of the customizations I use to help me get things done efficiently with Terminal:

# Display external and internal IP:
ip () {  
  echo 'External:' $(curl --silent ip.appspot.com)
  echo 'Internal:' $(ifconfig | grep 'inet' | grep 'broadcast' | awk '{print $2}')
}  

# Open Chrome.
alias chrome='open -a "Google Chrome"'

# Rotate path/to/image #degreesdegreesClockwise≥0
rotate () { sips -r $2 $1; }

# Show the CPU temperature.
# prereq: $ gem install iStats
alias temp='istats cpu temperature'

# Rename the current Terminal tab.
title () { printf "\e]1;$1\a"; }

# Serve the working directory at 0.0.0.0:8000. 
alias serve='python -m SimpleHTTPServer'

# Show/Hide hidden files in Finder
hiddenFiles(){  
  if [ $(defaults read com.apple.finder AppleShowAllFiles) = FALSE ] ; then 
    echo 'Showing hidden files.' && defaults write com.apple.finder AppleShowAllFiles TRUE
  else 
    echo 'Hiding hidden files.' && defaults write com.apple.finder AppleShowAllFiles FALSE
  fi
    killall Finder # Cycle
}

The following are some of the more useful suggestions from this guy's site:

# Add colors to Terminal's dark color theme.
export CLICOLOR=1  
export LSCOLORS=GxFxCxDxBxegedabagaced

#   Set Default Editor (change 'Nano' to the editor of your choice)
export EDITOR=/usr/bin/nano

# Recursive directory listing with $ lr
alias lr='ls -R | grep ":$" | sed -e '\''s/:$//'\'' -e '\''s/[^-][^\/]*\//--/g'\'' -e '\''s/^/   /'\'' -e '\''s/-/|/'\'' | less'  

Continuous Testing: Travis-CI

As with most things, it's easy once you know how:

1: In your project's root directory, include the following code in a .travis.yml file:

language: node_js  
node_js:  
  - "0.10"

2: Also, in your package.json, make sure to specify a test script command that runs your tests.

"scripts": {  
  "test": "gulp test"
},

3: Go to Travis and 'Sign in with GitHub' in the upper right.

4: Click on your user name and select 'Accounts'.

5: Turn on the repos you want to use with Travis, and click Sync now.
Travis-CI

6: Wait. Travis is running your tests; it could take a few minutes.

7: When it's done Travis will display a passing/failing build comment when you make a GitHub pull request.

travis on github

8: That's it! You can view the output of the tests on your Travis home page.

travis tests

Node.js + MongoDB + Grunt on Azure

I recently dove into another team's repo, intent on settting up continuous deployment to Azure.

The first step was to verify the app works locally. It uses Grunt tasks, an Angular client, a Mongo database, and an Express server, so I'm calling it the GAME stack.

mongoose kudu boar angular

Thankfully, the previous team (&| Yeoman) did a good job keeping Gruntfile.js up-to-date, so it didn't take much linting to get a local copy up and running.

I've already written about how to deploy a Node.js app to Azure, so those were the steps I followed, with two major differences:

MongoDB with MongoLab

Go to Azure and 'purchase' MongoLab for $0. (Follow these instructions if you're not sure how.)

Once you've got a MongoLab add-on, copy its connection string and the site name into the following commmand:

azure site connectionstring add MONGOLAB_URI [connectionString] Custom [siteName]  

Then you can reference your connection string in the production section of your code via process.env.CUSTOMCONNSTRMONGOLABURI like so:

mongoose.connect(process.env.CUSTOMCONNSTR_MONGOLAB_URI);  

Grunt with Kudu

So your database is set up, but you still need Grunt to build and start the server once it's on Azure. By default, Azure only runs npm and starts a node.js file. This requires a little bash scripting:

Generate default .deployment and deploy.sh scripts:

azure site deploymentscript --node  

Replace the deployment section in deploy.sh with the following (from this site)

echo 1. Selecting node version:  
selectNodeVersion  

echo 2. Installing npm packages:  
if [ -e "$DEPLOYMENT_SOURCE/package.json" ]; then  
  eval $NPM_CMD install  
  exitWithMessageOnError "npm failed"  
fi  

echo 3. Installing bower packages:  
if [ -e "$DEPLOYMENT_SOURCE/bower.json" ]; then  
  eval $NPM_CMD install bower  
  exitWithMessageOnError "installing bower failed"  
  ./node_modules/.bin/bower install  
  exitWithMessageOnError "bower failed"  
fi  

echo 4. Running grunt:  
if [ -e "$DEPLOYMENT_SOURCE/Gruntfile.js" ]; then  
  eval $NPM_CMD install grunt-cli  
  exitWithMessageOnError "installing grunt failed"  
  ./node_modules/.bin/grunt [tasks]  
  exitWithMessageOnError "grunt failed"  
fi  

echo 5. KuduSyncing to Target:  
"$KUDU_SYNC_CMD" -v 500 -f "$DEPLOYMENT_SOURCE/dist" -t "$DEPLOYMENT_TARGET" -n "$NEXT_MANIFEST_PATH" -p "$PREVIOUS_MANIFEST_PATH" -i ".git;.hg;.deployment;deploy.sh"  
exitWithMessageOnError "Kudu Sync to Target failed"  

Make sure to replace [tasks] with the grunt task(s) you want to execute in the production environment.

Run Node in Sublime

It's super simple, assuming you installed Node.js in the usual place: /usr/local/bin.

Navigate throught the Sublime menus to create a New Build System...

New Build System.

Replace the contents of the resulting file with the following code:

{
  "cmd": ["/usr/local/bin/node", "$file"],
  "selector": "source.js"
}

Save that file as Node.sublime-build in the default directory (which is ~/Library/Application\ Support/Sublime\ Text\ 3/Packages/User/).

Now you can hit ⌘b to have Node run your .js files from Sublime!

P.S. That "selector" property lets Sublime figure out what to do with .js files if Build System is set to Automatic. There's some misinformation online about using "*.js" rather than "source.js", however the former doesn't work.

Deploy Node app to Azure via GitHub

It's easier than you think; here's how:

Install Azure CLI

To install the Azure command line interface, run the following commands. (You can paste the bash code blocks into a temp.sh file and run it from terminal sh temp.sh).

npm install azure-cli -g  
azure account download  
read -p "Browser will download credentials file. Move it to Desktop then press enter."  
pathToCredentials=$(find ~/Desktop ~/Downloads -name "*credentials.publishsettings")  
azure account import $pathToCredentials  
rm $pathToCredentials  
azure account show  
azure site list  

If all went well, you should see information about your account and a list of your azure sites (if any).

Create an Azure site from GitHub

One liner time, ready?

azure site create [siteName] -–github  

Wait about 30 seconds, then see it live at siteName.azurewebsites.net!

Debug your deployment:

Edit IISNode.yml in the app's root directory to contain this:

loggingEnabled: true  

Now you can look at the live debug statements from your deployment in the command line! Here's the command:

azure site log tail [siteName]  

The best of all possible combinations

Geoff and I wrote some code to act as a base from which we can solve recursive combinitoric problems.

var binary = function(n, memo, result){  
  var choices = ["1","0"];
  result = result || [];
  memo = memo || "";
  for(var i = 0; i < choices.length; i++){
    // Pick a choice
    var nodeValue = choices[i];
    if( n < 1 ){ return []; }
    else if( n === 1 ){ result.push(memo+nodeValue); }         
    else { binary(n-1, memo+nodeValue, result); }
  }
  return result;
};

It has the benefit of not requiring any additional helper functions (looking at you prepend).

With this foundation, we were able to quickly adapt it to solve the telephoneNumbers problem.

File I/O w Node.js

The exercise today involved checking if strings are real words. It helps that OS X has a list of dictionary words at /usr/share/dict/words, so we could filter our strings against it. We just have to use node and node-fs to read in the file:

// Load fs module for node.
var fs = require('fs');  
// Read the file path with a specific encoding, then do callback.
fs.readFile('/usr/share/dict/words', "utf8", function read(err, data) {  
  if (err) { throw err; }
  // Split the input by line break into an array of words.
  array = data.split('\n');
  var content = {};
  // Add the words to an object to allow easy dictionary lookup.
  for (var i = 0; i < array.length; i++) {
    content[array[i]] = array[i];
  }
  // The filter returns only those strings in the dictionary.
  console.log( stringsToCheck.filter(function(string){
    // The double bang coerces the following to boolean.
    return !!dict[string.toLowerCase()];
  }));
});

Don't forget to $ npm install node-fs in the directory of this code before you run it on node.

That's it! Hopefully reading in files will be painless and helpful in the future.

Useful GitHub workflows

Quick-fix a typo or bug:
  1. Find a typo in someone else's repo.
  2. Fork the repo.
  3. Click on the file with the typo, then click edit in the upper right.
  4. Fix the typo and commit your change.
  5. Back out in your forked repo and click pull request.
  6. Edit the base and compare branches to conform to their contribution guidelines (eg they might not want you PRing to master).
  7. Click Create Pull Request, enter a great title and description.
  8. Submit!
Contribute to another repo:
  1. Do steps 1 and 2 of Quick-fix a typo or bug above.
  2. Copy the forked repo URL.
  3. On the command line, run git clone [repo URL].
  4. Set an upstream remote via git remote add upstream [original repo URL] to allow you to keep your cloned repo updated with changes in the original through git pull upstream master.
  5. Implement your changes in the cloned repo.
  6. Check what you've changed with git status.
  7. Add files you've changed via git add [file].
  8. Commit staged files: git commit -m"useful change description".
  9. Push your commit up to your repo with git push origin master.
  10. Do steps 5, 6, 7, and 8 of "Quick-fix a typo or bug" above.
Pair programming:

Use the steps of Contribute to another repo but create remotes to your fork of the original repo git remote add [your alias] [your fork URL] and push committed work to your forks git push [your alias] [branch to push].

For example, if I'm working with Joe on branch "pair" we might create the following remotes and push local commits to our forks like so:

git remote add mLubyRemote https://github.com/mLuby/theRepo.git  
git remote add remoteToJoe https://github.com/Joe/theRepo.git  
git push mLubyRemote pair  
git push remoteToJoe pair  

Prismatic Ghost: code syntax highlighting

Want to be able make beautiful code blocks like this?

this.beautifulCode.prototype = function(params){  
  var bob ? false || true && 1;
  return bob;
};

Then read on!

Installing Prism

We'll use Prism.js to prettify Ghost's default code blocks.

  1. Go to the Prism.js website, select the options you want, then download the prism.js and prism.css files. These are my suggested settings:

    • Compression level: Development version
    • Languages: Markup, CSS, CSS Extras, Javascript, Bash
    • Plugins: Line Highlight, Show Language
  2. Once you have the files, go to your server hosting Ghost, and look for your context/themes/[currentTheme] directory. Add prism.js to assets/js and prism.css to assets/css.

  3. Finally, open up default.hbs in your code editor. Look for the {{! Styles'n'Scripts }} section and append the following to it:

<link rel="stylesheet" href="/assets/css/prism.css">  

Also look for the {{! The main JavaScript file for GhostScroll }} section and add the following:

<script src="/assets/js/prism.js"></script>  

That's it for installation!

Using Prism

Now you're wondering how to use these beautiful code blocks.

When you write a post in Ghost, use ```language-[language] to begin the code block, and ``` to end it. You'll most likely be using language-markup, language-css, and language-javascript.

  ```language-javascript  
  this.beautifulCode.prototype = function(params){  
    var bob ? false || true && 1;  
    return bob;  
  };  
  ```

Customizing Prism

Cool, so Prism is now highlighting your syntax, but you want to make some changes to how it looks. Easy! Figure out what css selectors are working on the syntax styling you want to change, then go to the prism.css file and modify those selectors. It's as simple as that. (I used this to soften the language name in the upper right of code blocks, and to remove a white background on = signs.)

Advanced usage

Prism lets you draw attention to a specific line or section of code within your code block. To highlight a line (say line 2, as in the starting example), use the <pre class="language-javascript" data-line="2"><code> syntax to begin your code block, and </code></pre> to end it.

It's also worth noting that you can add line numbers to the entire block via this method. If you find an easier way, please let me know!

Don't sudo; reclaim permissions!

Recently I've been using a bunch of package managers, but each time I run something like npm install -g [cool command line tool] I get a nasty response from terminal:

npm ERR! Error: EACCES, open '/Users/myName/.npm/accepts/1.0.7/package/package.json'  
npm ERR!  { [Error: EACCES, open '/Users/myName/.npm/accepts/1.0.7/package/package.json']  
npm ERR!   errno: 3,  
npm ERR!   code: 'EACCES',  
npm ERR!   path: '/Users/myName/.npm/accepts/1.0.7/package/package.json',  
npm ERR!   parent: '[cool command line tool]' }  
npm ERR! Please try running this command again as root/Administrator.  
npm ERR! System Darwin 13.3.0  
npm ERR! command "node" "/usr/local/bin/npm" "install" "[cool command line tool]"  
npm ERR! node -v v0.10.29  
npm ERR! npm -v 1.4.14  
npm ERR! code EACCES  
npm ERR! errno 3  
npm ERR! stack Error: EACCES, open '/Users/myName/.npm/accepts/1.0.7/package/package.json'  
npm ERR! not ok code 0  

As you can see from line 7, npm fails because I don't have permissions to modify the directories that it's asking to use.

The quick and very dirty solution to this is to rerun the command with sudo permission: sudo !! (which is the same as running sudo npm install -g [cool command line tool].

But really, we want to fix the problem for good. Internet to the rescue!

The gist is that we need to reclaim permissions for the directories npm is complaining about.

Here's how:

sudo chown -R `whoami` ~/.npm  
sudo chown -R `whoami` /usr/local  
sudo chown -R `whoami` /usr/local/lib  
sudo chown -R `whoami` /usr/local/lib/node_modules  

These commands use sudo permissions to reclaim access to those 4 directories for the current user (found via `whoami`).

Now that you have permanent permission, the original command will run without sudo: npm install -g [cool command line tool].