The Hacker said over 5 years ago permalink Comment? (0)
Tagged: ruby rails gem geocoding google

Google-Geocode Gem Woe's

While using the very cool google-geocode gem for ruby, I ran into a small (read: big) problem.

Do a search for “Trinidad” by itself and you get something like:

Communication error: #<REXML::ParseException: Missing end tag for 'AdministrativeAreaName' (got "AdministrativeArea")

The problem lies not in the gem but in ruby’s REXML and how it deals with the xml google sends back. This only happens when international characters are involved.

After doing a little googling I saw a patch for rexml which I changed into a monkey patch for google-geocodes helper library rc-rest.

This monkey patch will solve all your accent mark woe’s.

class RCRest
  
  def get(method, params = {})
    url = make_url method, params

    url.open do |xml|
      body = xml.read

      res = REXML::Document.new Iconv.conv("UTF-8//Ignore", 'UTF-8', body)
  
      check_error res

      return parse_response(res)
    end
  rescue IOError, SystemCallError, SocketError, Timeout::Error,
         REXML::ParseException => e
    raise CommunicationError.new(e)
  rescue OpenURI::HTTPError => e
    begin
      xml = REXML::Document.new e.io.read
      check_error xml
    rescue REXML::ParseException => e
    end
    new_e = CommunicationError.new e
    new_e.message << "\n\nunhandled error:\n#{xml.to_s}"
    raise new_e
  end
  
end

The magical change is the inclusion of Iconv to make REXML happy.

The Hacker said over 4 years ago permalink Comment? (0)
Tagged: rails geocoding stubbing

GeoKit stubbing for faster tests

We recently added geocoding to after_save on an address model to keep track of peoples lat/lng, and found that it added substantial time to our tests. The solution? Easy.

Don’t really need to test that geolocating works, I mean.. GeoKit has its own unit tests. So Stub it! Stub it good!

Place this in your test_helper.rb (and inside Test::Unit::TestCase) for tolerable test times.

“This was written for mocha, but its easy to adapt to rspec or flexmock”

  setup :stub_geocoder
  def stub_geocoder
    geocode_payload = GeoKit::GeoLoc.new(:lat => 123.456, :lng => 123.456)
    geocode_payload.success = true
    GeoKit::Geocoders::MultiGeocoder.stubs(:geocode).returns(geocode_payload)
  end

“Just remember to turn it off if you plan to test any features that rely on actual geocoding!”