Suffix

Published by Simon Schoeters

From Dopplr to OpenStreetMap

In one of my previous posts I showed how to dynamically generate a map from a set of coordinates in Ruby on Rails (like the map on top of this page). This is nice but still required me to manually update my location each time... not very useable. I have a Dopplr account where I enter all my future trips so it feels stupid to enter the same information again on my own website. We can do better than that!

Here is the idea: a script that checks my travel plans on Dopplr for to following day and creates a new map of that location if needed. Also: a perfect excuse to have a look at the Rake build language which I had never used.

Dopplr API

The Dopplr API includes a Ruby client which makes our life easier, download the ‘Improved Ruby Client’ in your <yourapp>/lib folder so we can use it later on.

Tokens and sessions

You will need a session key to use the Dopplr API, this key replaces your username and password (read ‘The password anti-pattern’ if you want to know why). Here is how to get one:

  1. Go to https://www.dopplr.com/api/AuthSubRequest?scope=http://www.dopplr.com&next=<your_url>&session=1. Replace <your_url> with your website's URL.
  2. Once approved you will be redirected to your URL with a token=<token_hash> parameter, copy the token value.
  3. Start your Rails development console to convert the token to a session hash with ./script/console.
  4. Upgrade the token to a session:
    >> d = Dopplr.new
    >> d.set_token("<token_hash>")
    >> d.upgrade_to_session

  5. Copy the result - this is your session key - and keep it somewhere safe.

Rake task

I wanted something outside this website that could run automatically, even when the website wasn't opened. Rake offers you a way to do this: you can build and run scripts independently from the rest of the application while using the same environment as the application.

Here is a simplified version of the task I created. Copy this and save it in your <yourapp>/lib/tasks folder as map.rake.

namespace :map do
  desc "Overwrites the map with my Dopplr location on a given date"
  task :date => :environment do
    c = define_coordinates(ENV['date'])
    create_map(c['lat'], c['long'], 1200, 100, 0.3, 8)
  end

  desc "Updates the map.png with a map of my current Dopplr location"
  task :update => :environment do
    today = Time.now
    c = define_coordinates(today.strftime("%Y%m%d"))
    create_map(c['lat'], c['long'], 1200, 100, 0.3, 8)
  end

  # Extract the coordinates from the Dopplr API
  def define_coordinates(date)
    d = Dopplr.new
    d.set_token(<session_key>)
    loc = d.location_on_date(:date => date)['location']
    if loc.has_key?('trip')
        {"lat" => loc['trip']['city']['latitude'], "long" => loc['trip']['city']['longitude']}
      else
        {"lat" => loc['home']['latitude'], "long" => loc['home']['longitude']}
    end
  end

  # Create a new OpenStreetMap with the given coordinates
  def create_map(latitude, longitude, width = 500, height = 500, opacity = 1, zoom = 7)
    [...]
  end
end

Now, check your taks with rake -T. You'll get an overview of all the Rake tasks for your app and there should be a ‘map:date’ and ‘map:update’ one. This means you can run these scripts interactively now:

rake map:date date=20080101
Will create/overwrite the map.png file in the /public/image folder with a map of you Dopplr location on January 1st, 2008.
rake map:update
Will also create a map but with your current Dopplr location.

Cron

Almost done. We can now create a new map whenever we want on any given date. Let's run this script each night at 4 in the morning. Add the following line to your crontab:

0 4 * * * cd <app_path> && /usr/local/bin/rake map:update RAILS_ENV=production

That's it. The script will now look for your current location in your Dopplr account and create a map based on that location.