2010-01-01 6 views
13

Mi sembra che la libreria YAML fornita con Ruby 1.9 sia codifica-sorda.Ruby 1.9, YAML e string encodings: come condurre una vita di sanità mentale?

Ciò significa che durante la generazione di YAML prenderà qualsiasi stringa di byte ed eviterà qualsiasi sequenza di byte che non restituisca ASCII pulito. È zoppo, ma accettabile.

Il mio problema è il contrario. Quando si carica il contenuto da detto dump YAML.

Nell'esempio che segue creo una stringa UTF-8, esegui il dump, viene scaricata con il tipo !binary. Quando lo carico, ha la codifica ASCII-8BIT. Alla fine dell'esempio cerco di concatenare sia la stringa originale che quella ricaricata con un'altra stringa UTF-8. Quest'ultimo fallirà con un Encoding::CompatibilityError.

require 'yaml' 
s0 = "Iñtërnâtiônàlizætiøn" 
y = s0.to_yaml 
s1 = YAML::load y 
puts s0     # => Iñtërnâtiônàlizætiøn 
puts s0.encoding  # => UTF-8 
puts s1     # => Iñtërnâtiônàlizætiøn 
puts s1.encoding  # => ASCII-8BIT 
puts y     # => --- !binary | 
         # ScOxdMOrcm7DonRpw7Ruw6BsaXrDpnRpw7hu 
puts "ñårƒ" + s0  # => ñårƒIñtërnâtiônàlizætiøn 
puts "ñårƒ" + s1  # => Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT 

penso che sia chiaro come questo porterà rapidamente a problemi quando hai a che fare con qualche fonte YAML contenente hash nidificati e array di stringhe con foglia.

Attualmente ho un codice che attraversa tutti gli hash e gli array e chiama force_encoding su ogni stringa. Quello, per non dire altro, è antiestetico.

Quello che sto cercando in questo momento è un modo per dire che YAML::load qualsiasi stringa che viene in dovrebbe essere trattata come, e quindi hanno la sua codifica UTF-8.


Idealmente, lo YAML di Ruby dovrebbe solo annotare le stringhe con la corretta codifica. C'è un progetto Ya2YAML che tenta di scaricare YAML in modalità UTF-8. Non sono sicuro di quanto sia lungo. Se qualcuno ha giocato con esso, accolgo qualsiasi pensiero.

Indipendentemente da ciò, ho ancora questi dump senza informazioni di codifica da gestire. Anche se so che sono tutti UTF-8.

+2

+1 per le dieresi di metalli pesanti. –

+0

Mi sono imbattuto nello stesso bug/comportamento ... Hai trovato un'altra soluzione o stai ancora solo facendo YAML.load e poi force_encoding ('utf-8') su ogni stringa? – severin

risposta

1

In primo luogo il file di testo che si sta tentando di leggere deve essere codificato in UTF-8 (questo dovrebbe essere il file YAML).

Quindi aggiungere questa linea alla parte superiore del file rubino, hash e tutto

# encoding: UTF-8 

Ciò significa che la codifica predefinita per tutte le stringhe sarà UTF-8, e dovrebbe significare che qualsiasi testo di eseguire il dump con YAML.dump ('testo') o anche stringhe letterali 'come questo' dovrebbero anche essere codificati in UTF-8, e tutti dovrebbero funzionare bene da qui in avanti.

+0

Non importa. Stuff read as! Binary dallo yaml finisce come ASCII-8BIT, per ragioni forse ovvie e sane, ma così yaml dovrebbe scaricare correttamente le stringhe UTF8 senza escape. Ho più o meno una soluzione a questo, ma comporta un buon codice. Pubblicherò una risposta quando avrò una gemma pronta. – kch

3

Considerare di aggiornare il tuo rubino all'ultimo 1.9.2 .

Ho trovato questo errore in 1.9.1 ma non 1.9.2.

2
YAML::ENGINE.yamler='psych' 
'Résumé'.to_yaml # => "--- Résumé\n...\n" 
0

risposta di Evgeny mostra ancora binario per me, ma questo funziona (instoad 'syck' di 'psych'):

YAML::ENGINE.yamler='syck' 
'Résumé'.to_yaml # => "--- "R\xE9sum\xE9" 

sto usando Ruby 1.9. Nota per i miei scopi avere gli speciali essere sfuggiti va bene - ho solo bisogno di non mostrare! Binario ... per parole normali. Grazie a dio .to_yaml è di nuovo funzionale per me - usato per usarlo tutto il tempo. Come caricare davvero una vita di sanità mentale :)

+0

Grazie per quella correzione user1262147 - yamler = 'psych' non ha fatto nulla per me, ma yamler = 'syck' l'ha risolto. In precedenza to_yaml stava scaricando tutto come! Binary = whatever - persino i nomi degli attributi di un ActiveRecord proveniente da una tabella mysql UTF8. –

+0

La risposta è obsoleta, era obsoleta quando è stata effettuata, syck è obsoleto – bbozo