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:
- 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.
- Once approved you will be redirected to your URL with a token=<token_hash> parameter, copy the token value.
- Start your Rails development console to convert the token to a session hash with ./script/console.
- Upgrade the token to a session:
>> d = Dopplr.new
>> d.set_token("<token_hash>")
>> d.upgrade_to_session - 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.