2014-07-01 23 views
5

si prega di seguire il codice:Perché HAML gettare codifica problema quando ERB e ERUBIS dont

__ENCODING__ 
# => #<Encoding:UTF-8> 

Encoding.default_internal 
# => #<Encoding:UTF-8> 

Encoding.default_external 
# => #<Encoding:UTF-8> 

Caso 1: HAML getta Encoding::UndefinedConversionError

string = "j\xC3\xBCrgen".force_encoding('ASCII-8BIT') 

string.encoding 
# => #<Encoding:ASCII-8BIT> 

Haml::Engine.new("#{string}").render 
## => Encoding::UndefinedConversionError: "\xC3" from ASCII-8BIT to UTF-8 

ERB.new("<%= string %>").result(binding) 
# => "jürgen" 
# => Resulting encoding is #<Encoding:UTF-8> 

Erubis::Eruby.new("<%= string %>").result(binding)  
# => "j\xC3\xBCrgen" 
# => resulting encoding is #<Encoding:ASCII-8BIT> 

Caso 2: HAML non si butta error

Domanda: Perché HAML fallendo nel caso 1 e riuscendo nel caso 2

questo che sto chiedendo sto affrontando il problema simile quando un rendering in HAML che saltare pagina a causa di Encoding :: CompatibilityError

L'unico modo in questo momento penso di sapere come evitare l'errore questo è fare un force_encoding della mia stringa a UTF8 usando .force_encoding('UTF-8') che tipo di evitare questo problema, ma devo farlo in ogni pagina in cui voglio usare il dato stringa cioè "j \ xc3 \ xBCrgen" (che ho trovato un po 'stupido per fare considerando le loro molte pagine)

Qualsiasi indizio? ?

+0

Cosa succede se si passa la stringa direttamente alla chiamata 'Engine.new()' senza interpolarla? – screenmutt

risposta

1

Haml sta tentando di codificare la stringa del risultato sull'impostazione Encoding.default_internal. Nel primo esempio la stringa ("j\xC3\xBCrgen") contiene byte non ASCII (cioè byte con il set di bit alto), mentre la stringa nel secondo esempio ("Ratatouille") no. Ruby può codificare la seconda stringa (poiché UTF-8 è un superset di ASCII), ma non può codificare il primo e genera un errore.

Un modo per lavorare intorno a questo è di passare in modo esplicito la codifica stringa come un'opzione per Haml::Encoding:

Haml::Engine.new("#{string}", :encoding => Encoding::ASCII_8BIT).render 

questo vi darà una stringa risultato che è anche ASCII-8BIT.

In questo caso, la stringa in questione è UTF-8, quindi una soluzione migliore potrebbe essere quella di controllare da dove proviene la stringa nell'app e assicurarsi che abbia la codifica corretta.

Non so abbastanza su ERB e Erubis per dire cosa sta succedendo, sembra che ERB stia erroneamente supponendo che sia UTF-8 (ha ora modo di sapere che quei byte dovrebbero essere trattati come UTF-8) Erubis sta facendo la cosa più sensata di lasciare la codifica come binaria - o perché non sta facendo alcuna codifica, o sta trattando specialmente l'input codificato in formato binario.

+0

Si potrebbe sostenere che l'aumento di un errore qui è un bug in Haml. Non sono sicuro di come gli altri utenti di 'default_internal' gestiscono questo, potrebbe essere meglio lasciare i file binari invariati. – matt

+0

Sì, anche io ho sentito che sollevare un errore in HAML è un po 'ritardato poiché la codifica interna predefinita è 'UTF-8' e presumo che" j \ xC3 \ xBCrgen "sia una stringa UTF-8 valida – Ratatouille

+0

Quindi per sbarazzarsi di errore usa sempre 'force_encoding ('UTF-8')' è quello che dovrei prendere dalla risposta sopra corretta – Ratatouille

1

Dal libro PickAxe:

Rubino supporta una codifica virtuale chiamato ASCII-8BIT. Nonostante l'ASCII nel nome, questo è realmente destinato a essere utilizzato su flussi di dati che contengono dati binari (motivo per cui ha un alias di BINARY}). Tuttavia, puoi anche usarlo come codifica per i file sorgente. Se lo fai, Ruby interpreta tutti i caratteri con codici sotto 128 come ASCII regolari e tutti gli altri caratteri come costituenti validi di nomi di variabili. Questo è fondamentalmente un bel trucco, perché consente a di compilare un file scritto in una codifica che non si conosce: si presume che i caratteri con il set di ordine di alto ordine siano stampabili.

String#force_encoding indica a Ruby quale codifica utilizzare per interpretare alcuni dati binari. Non cambia/converte i byte effettivi (che sarebbero String#encode), cambia semplicemente la codifica associata a questi byte.

Perché dovresti provare ad associare una codifica BINARY ad una stringa che contiene comunque caratteri UTF-8?

quanto riguarda la tua domanda sul motivo per cui il secondo caso ha successo la risposta è semplicemente che il vostro seconda stringa ("Ratatouille") contiene solo caratteri ASCII a 7 bit.