2010-08-16 24 views
0

Je suis actuellement en train d'écrire une application rails en utilisant des trucs de pointe. Rails3, rSpec2, Ruby 1.9.2 et Geokit 1.5.0. Lorsque je tente de géocodage des adresses qui ont des caractères spéciaux qui ne sont pas en ASCII 8bit je reçois cette erreur:Geokit Gem 1.5 et Ruby 1.9.2 => "encodages de caractères incompatibles: UTF-8 et ASCII-8BIT"

incompatible character encodings: UTF-8 and ASCII-8BIT

La Trace est comme ceci:

1) Spot Basic Validations should calculate lat and lng 
    Failure/Error: spot = Spot.create!({ 
    incompatible character encodings: UTF-8 and ASCII-8BIT 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/geokit-1.5.0/lib/geokit/geocoders.rb:435:in `do_geocode' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/geokit-1.5.0/lib/geokit/geocoders.rb:126:in `geocode' 
    # ./app/models/spot.rb:26:in `geocode_address' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb:409:in `_run_validation_callbacks' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activemodel-3.0.0.rc/lib/active_model/validations/callbacks.rb:53:in `run_validations!' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activemodel-3.0.0.rc/lib/active_model/validations.rb:168:in `valid?' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/validations.rb:55:in `valid?' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/validations.rb:75:in `perform_validations' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/validations.rb:49:in `save!' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/attribute_methods/dirty.rb:30:in `save!' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/transactions.rb:242:in `block in save!' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/transactions.rb:289:in `block in with_transaction_returning_status' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in `transaction' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/transactions.rb:204:in `transaction' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/transactions.rb:287:in `with_transaction_returning_status' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/transactions.rb:242:in `save!' 
    # /Users/nilsriedemann/.rvm/gems/ruby-1.9.2-rc2/gems/activerecord-3.0.0.rc/lib/active_record/validations.rb:34:in `create!' 
    # ./spec/models/spot_spec.rb:13:in `block (2 levels) in <top (required)>' 

J'utilisé # coding: utf-8 dans tous mes associés fichiers (spécifications, usines et modèle). Pourtant, je reçois cette erreur quand j'utilise une adresse comme "Elsassers Straße 27".

Des indices? Je pensais que Geokit était déjà compatible avec 1.9.1 et donc avec toute cette nouvelle chose d'encodage.

+0

Il y a un problème avec l'enregistreur au mieux que je peux dire qui génère les erreurs de codage. Cependant, Geokit ne gère toujours pas correctement certaines entrées. Pour moi, c'est barfant sur l'entrée japonaise. J'essaie de produire un patch. –

+1

J'ai ajouté un test à une fourche de la gemme GeoKit que j'ai faite et cela fonctionne avec des adresses japonaises. Mais quand j'utilise cette gemme fourchue dans mon application Rails 3 sur Ruby 1.9.2, je reçois toujours l'erreur d'encodage. –

Répondre

0

Utilisez-vous Postgres et pg gem v0.8? Mise à niveau vers 0,9

0

Je sais que c'est une réponse très très tard, mais j'ai écrit un géocodeur Google pour la gemme Geokit qui gère toutes ces erreurs d'incompatibilité. Ce géocodeur utilise la toute dernière API V3 du service de géocodage de Google. L'avantage est que maintenant il n'analyse pas XML mais plutôt JSON qui est plus rapide, couplé avec le joyau requis Yajl (un analyseur json super rapide pour ruby) est beaucoup plus rapide. Mes tests montrent environ 1,5 fois plus rapide que l'ancienne méthode.

https://github.com/rubymaniac/geokit-gem

-1

J'ai eu le même problème et je résolu ce problème en ajoutant cgi.escape() comme ceci:

geo = Geokit::Geocoders::MultiGeocoder.geocode(CGI.escape(address)) 
+0

il ne fonctionne pas pour á, é, ã et autres :( –

3

cgi.escape n'est pas Utilisation d'une bonne idée, car il donne des résultats inattendus . Essayez "Oslo, Norvège" avec et sans CGI.escape, vous verrez ce que je veux dire.

Une meilleure solution est d'utiliser Iconv sur l'emplacement:

ic = Iconv.new('US-ASCII//IGNORE', 'UTF-8') 
utf8location = ic.iconv(location) 

Cheers!

EDIT: J'ai eu une suggestion de Wes Gamble pour modifier ici, que je pense est pertinent:

L'utilisation //IGNORE enlèvera tous les caractères non-ASCII. Mais dans la plupart des cas, vous pouvez vouloir translittérer certains caractères tels que les trémas (par exemple "Zürich" deviendra "Zurich") ou les carons (par exemple "Niš" deviendra "Nis") afin de les géocoder avec succès. Si vous ignorez les caractères non-ASCII, alors "Zürich" deviendra "Zrich" et "Niš" deviendra "Ni", aucun des deux ne sera géocode avec succès.

Pour cela, vous voulez utiliser

ic = Iconv.new('US-ASCII//TRANSLIT', 'UTF-8') 

Notez que la conversion lancera une exception si la translittération ne peut pas être terminée alors assurez-vous gérer cela.

1

CGI.escape semble être plus précis que Geokit :: Inflector :: url_escape.

Voici les résultats du codage "Elsassers Straße 27"

>> CGI.escape(address)

=> "Elsassers+Stra%C3%9Fe+27"

Alors que

>> Geokit::Inflector::url_escape(address)

=> "Elsassers+Stra%C3e+27"

La lettre ß doit montrer que c39F (selon http://www.utf8-chartable.de/unicode-utf8-table.pl)

En outre, la déclaration de débogage soufflait (je savais qu'il y avait des raisons de vérifier si l'enregistrement de débogage est activé :)

Donc, voici ma solution pour GoogleGeocoder3, je suppose que d'autres auront un problème similaire

module Geokit 
    module Geocoders 
    class GoogleGeocoder3 < Geocoder 
     def self.do_geocode(address, options = {}) 
     bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : '' 
     address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address 
     #use CGI.escape instead of Geokit::Inflector::url_escape 
     url ="http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{CGI.escape(address_str)}#{bias_str}" 
     res = self.call_geocoder_service(url) 
     return GeoLoc.new if !res.is_a?(Net::HTTPSuccess) 
     json = res.body 
     # escape results of json 
     logger.debug "Google geocoding. Address: #{address}. Result: #{CGI.escape(json)}" 
     return self.json2GeoLoc(json, address) 
     end 
    end 
    end 
end 
+0

en fait, après tout cela, quand j'ai envoyé une demande de traction, on dirait qu'il y avait déjà une solution pour ce https://github.com/andre/geokit- gem/pull/35/fichiers – katzmopolitan