Tuesday, July 19, 2011

The ask_geo gem: find the time zone for a given latitude and longitude

The Google Maps API has all kinds of great services like geocoding and reverse geocoding, but it lacks an API to determine a timezone from a latitude and longitude. This kind of service would come in handy, for example, when you are picking a point on Earth and scheduling an event there in the point's local time. It could also be useful for automatically determining a website visitor's current local time based on the geolocation obtained from their browser or IP address.

There is a service called GeoNames, which comes close to serving this need. However, its look-ups are based on "closest point of interest", which means that you can get errors when you are near borders, and some locations may not return any results at all.

There is another service called EarthTools which doesn't have this problem, but it only returns the current offset from UTC at that point. That is great if you only care about the current local time, but leaves you stranded if you need to account for Daylight Savings Time on some future or past date.

After a bit of searching, I came across a great free service called AskGeo. AskGeo provides a very simple JSON-over-HTTP API (or XML if you prefer to party like it's 1999). AskGeo uses a real time zone map, so every point on earth returns a result, and returns real Olson IDs for time zones, so you can look up DST transitions, leap seconds, etc.

I gave AskGeo a try and it works great...and it's fast! Since there was no ready-made Ruby gem that provided a client API, I decided to create one.

Introducing the ask_geo gem: https://github.com/scottwb/ask_geo

It can be installed as a ruby gem. See the github page for installation and usage instructions.

Sunday, July 10, 2011

Custom RSpec be_square matcher for CarrierWave

It seems to me that when using CarrierWave for image uploads, particularly user avatars, it would be a pretty common thing to generate at least one square-cropped version of the image. CarrierWave ships with some nice custom matchers to test exact dimensions and such, but I found I wanted a way to just test that an image was square.

I did this using by building a custom matcher on top of the ones CarrierWave provides. If you have the conventional spec_helper.rb that requires support/**/*.rb, then you can just drop this somewhere like support/matchers/carrierwave_matchers.rb:

Then, you can use this like: