Suffix

From Dopplr to OpenStreetMap

Generate an image of a map based on your current Dopplr location with Ruby.

In one of my earlier posts I explained how to dynamically generate a map from a set of coordinates in Ruby on Rails (there used to be a dynamic map in a previous design of this site). This still requires me to manually update my location, not very useable. I have a Dopplr account where I enter all my future trips. I could simply get my location from them.

A script that checks my travel plans on Dopplr for the 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.

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 open. 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 .
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

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