Sönke Rohde

Zsh Shell

The terminal is next to the editor probably the most important tool for a developer. Being comfortable executing shell commands increases productivty significantly. And that’s what it’s about at the end. Being able to focus on solving the problem and not dealing with tools and workflows to get there. For a long time I am using iTerm 2 but that’s only the terminal and does not change the actuall shell.

I was browsing dotfiles and came across zsh, an alternative to the default bash shell on OSX.

I’ve been using zsh for a couple of weeks now and like especially the dot-files oh-my-zsh which provide a great default configuration and git prompts. Here the steps on how I’ve set things up:

Make zsh default shell:

chsh -s /bin/zsh

Open a new terminal window to see zsh!

Install oh-my-zsh (you gotta trust that script so make sure you want to do that):

curl -L https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh | sh

Now some configiration. Edit ~/zshrc. I like the default theme but set ZSH_THEME="random" and open some new shells to explore some other themes you might like better.

Oh-my-zsh comes with a bunch of plugins and only a few are set by default. Here is my plugin list:

plugins=(cake git sublime osx git-flow git-extras npm node theme web-search battery)

I always use the Sublime Text 2 plugin which just creates a st alias.

The web-search plugin is quite nice since now you can google or bing from the command line:

$ google bing
$ bing google

Explore all the plugins in ~/.oh-my-zsh/plugins to enable what fits your workflow. I discovered git-extras doing this which is really awesome.

If you want to use z here two lines how to set it up:

git clone git@github.com:rupa/z.git ~/.z
echo \\n. ~/.z/z.sh >> ~/.zshrc

Location Based Services With MongoDB

MongoDB is an open-source NoSQL database. It offers great features to build Location Based Services with build in support for Geospatial Indexes and Queries.

I’ve been using MongoDB with Node.js on Heroku so here a quick walk through on how to set it up and use it:

Setup

Local

Install and Run:

$ brew install mongo
$ mongod

On lesson I’ve learned is to always try to use MongoDB from the shell first before you start with actual code. After having the command right in the shell translate it into code and test your actual implementation. Here some shell commands to get you started:

$ mongo
> use mydbname

For this example we store locations in a collection called locations Make sure you have set the geo spacial index:

> db.locations.ensureIndex({loc: '2d'})
> db.locations.getIndexKeys()

Should output [ { "_id" : 1 }, { "loc" : "2d" } ]

Heroku

On the Heroku side it’s pretty easy to set up as well:

$ heroku addons:add mongohq:sandbox

To make sure the location index is also working on Heroku, login, select your app and select the MongoHQ add-on. This brings you to the MongoHQ admin interface. Then select your locations collection and make sure the Indexes are configured correctly. In my case it shows as { key: { loc: "2d" }, v: 1, ns: "appXXX.locations", name: "loc_2d" }

MongoDB Shell

Insert Location

When you insert a new location it’s essential to store the location in an array with [lon, lat] and not [lat, lon]. This was a mistake I made first and it took me a while to figure that out because all my queries were returning the wrong stuff.

Let’s insert some example locations (I’ve been using LATLONG.net):

> db.locations.insert({name: "Ferry Building", city: "San Francisco", loc:[-122.3937, 37.7955]})
> db.locations.insert({name: "Union Square", city: "San Francisco", loc:[-122.407437, 37.787994]})
> db.locations.insert({name: "Duboce Park", city: "San Francisco", loc:[-122.433453, 37.769422]}) 
> db.locations.insert({name: "Parque Ibirapuera", city: "São Paulo",loc:[-46.657490, -23.586996]})
> db.locations.insert({name: "Big Ben", city: "London",loc:[-0.124575, 51.500705]})
> db.locations.insert({name: "Fischmarkt", city: "Hamburg",loc:[9.937740, 53.544527]})
> db.locations.insert({name: "Opera House", city: "Sydney",loc:[151.214993, -33.857767]})

Now you can query all locations with:

> db.locations.find()

Just as a sanity check: Everything west of Greenwich has a longitude < 0 and east > 0. Everything in the northern hemisphere has a latitude > 0 and in the southern hemisphere < 0 or as Wikipedia puts it:

In geography, latitude (φ) is a geographic coordinate that specifies the north-south position of a point on the Earth’s surface. Latitude is an angle (defined below) which ranges from 0° at the Equator to 90° (North or South) at the poles.

http://en.wikipedia.org/wiki/Latitude

Longitude (/ˈlɒndʒɨtjuːd/ or /ˈlɒŋɡɨtjuːd/),[1] is a geographic coordinate that specifies the east-west position of a point on the Earth’s surface. […] The longitude of other places is measured as an angle east or west from the Prime Meridian, ranging from 0° at the Prime Meridian to +180° eastward and −180° westward.

http://en.wikipedia.org/wiki/Longitude

Query Locations

After we have inserted some test locations let’s try to make a geospatial query. In my case I wanted to find locations close to the current location so let’s pretend we are at the Ferry Building in San Francisco.

> db.runCommand({geoNear: "locations", near: [-122.3937, 37.7955], num: 10, spherical:true})

The result is ordered by distance and the Ferry Building should be on top with a dis of 0. To have the distance in a human readable unit you can use the distanceMultiplier attribute and select for instance the earth radius in miles which is 3959. This will show all distances in miles:

> db.runCommand({geoNear: "locations", near: [-122.3937, 37.7955], num: 10, spherical:true,
distanceMultiplier: 3959})

If you want to restrict the search to a radius like 10 miles you’ll have to use the maxDistance attribute:

> db.runCommand({geoNear: "locations", near: [-122.3937, 37.7955], num: 10, spherical:true,
distanceMultiplier: 3959, maxDistance:10/3959})

If you want kilometers use 6371m as the radius of the earth.

Now that everything is working in the shell we can start with actual code.

Node.js Code

This example is written with CoffeeScript and has been extracted from an actual project and usually you would do more validation and parsing but you should get the idea on how the Express route is working:

1
2
3
4
5
6
7
8
# app.coffee
express = require 'express'
api = require './routes/api'
app = module.exports = express()

apiVersion = 'v1'
app.post "/api/#{apiVersion}/location", api.location
app.get "/api/#{apiVersion}/location", api.location
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# routes/api.coffee
mongo = require 'mongodb'
assert = require 'assert'

ObjectID = mongo.BSONPure.ObjectID

dbConnection = process.env.MONGOHQ_URL or 'mongodb://localhost/mydbname'

locations = null
db = null

mongo.Db.connect dbConnection, (err, database) ->
  db = database
  assert.equal null, err

  database.collection 'locations', (err, collection) ->
    assert.equal null, err
    locations = collection

exports.location = (req, res) ->
  switch req.method

    # Create location
    when 'POST'
      # In this example I am using upsert to update the record with the existing _id when present or create a new ObjectID if not:

      location = req.body
      location.loc = [parseFloat(location.loc[0]), parseFloat(location.loc[1])]

      isUpdate = location._id?
      id = if isUpdate then location._id else new ObjectID()

      locations.update {_id:id}, location, {upsert:true, safe:true}, (err, result) ->
        assert.equal null, err
        res.send JSON.stringify(location)

    # Query locations
    when 'GET'
      lat = req.query["lat"]
      lon = req.query["lon"]

      if lat and lon
        lat = parseFloat lat
        lon = parseFloat lon

        # validate that lat/lon are numeric
        return res.send 400 if isNaN(lat) or isNaN(lon)

        # validate that lat/lon are in the right range
        return res.send 400 if lon < -180 or lat > 180

        geoNear = 
          geoNear: locations
          near: [lon, lat]
          spherical: true
          maxDistance: 10 / 3959
          distanceMultiplier: 3959

        db.command geoNear, (err, locations) ->
          assert.equal null, err
          res.send locations

Testing Node.js Express Routes

Lately I needed some tests for an Express Node.js project I was working on and I was surprised how easy and minimalistic the code can look like with CoffeeScript. Check out this gist:

I am using should.js as the assertion library and mocha as the testing framework. In this example I am testing a login function. My Node.js route (api.coffee) is being imported and then I’ll first test if the login function actually exists. After that I am invoking the login function and make assertions against the result. The implemented function signature looks like this:

1
exports.login = (req, res) ->

The parameters are request and response. This route is using GET so for the request parameter we’ll specify the query parameters. When the implementation is done with the login execution it’ll call res.send(result) so it’s perfect to hook into that as well and we can do assertions against the result type and value.

If you are new to CoffeeScript this might look a bit cryptic but let me show you how the JavaScript would look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Generated by CoffeeScript 1.6.2
(function() {
  var api, should;

  should = require('should');

  api = require('../../routes/api');

  describe('api', function() {
    return describe('#login()', function() {
      return it('should login a user', function(done) {
        api.login.should.be.a('function');
        return api.login({
          query: {
            email: "foo@gmail.com",
            password: "secret"
          }
        }, {
          send: function(result) {
            result.should.be.a('object');
            result.email.should.equal("foo@gmail.com");
            return done();
          }
        });
      });
    });
  });

}).call(this);

New Blog With Octopress

I’ve been blogging using Workpress since February 2005 and I think Wordpress made the Internet a better place. Luckily I never got hacked but there are just too many stories that sites got hijacked that I finally decided to switch to a static blog. Github pages with Octopress seemed like a perfect fit for my needs so here we are.

The setup is dead simple so here my steps:

Created a new Github repo srohde.github.io and a bunch of command lines to initialize Octopress:

git clone git://github.com/imathis/octopress.git octopress
cd octopress
gem install bundler
bundle install
rake install
rake setup_github_pages\[git@github.com:srohde/srohde.github.io.git\] 
rake generate & rake deploy

Bam! The static site is up! Now also commit the sources to the source branch:

git add .
git commit -am "initial commit"
git push origin source

Creating a first post (this very one) couldn’t be easier:

rake new_post\["Blog with Octopress"\]
subl source/_posts/2013-06-07-blog-with-octopress.markdown
rake generate & rake deploy

And committing the updated and new sources again:

git add .
git commit -am "first post"
git push origin source

Bamgain (did I just invent that?)! I’ve got a bunch of topics I wanted to blog about and having a new blogging engine will motivate me to actually do so. That’s how devs tick I guess. Cheers!