Uma solução para problemas de charset com Oracle e Rails
Ontem comentei o meu problema com charset entre Oracle e uma aplicação web que estou fazendo. O problema era o seguinte: ao preencher campos de texto de um formulário com caracteres acentuados, os mesmos eram inseridos como se fossem dois caracteres de interrogação (??).
Essa aplicação tem como pré-requisito o uso de UTF-8, pois é feita com o framework Ruby on Rails. Minhas buscas pelo Google tinham me colocado apenas em uma direção: modificar o charset do banco de dados a partir de um penoso procedimento de backup/restore. Mas, conversando com o meu colega de trabalho Luiz (que não tem blog, infelizmente) descobri que ele já havia tido o mesmo problema antes e a solução, aparentemente, era bem mais simples (e mágica).
O Rails interage com o Oracle por intermédio da biblioteca Ruby oci8.
A solução mágica consiste em definir a variável de ambiente NLS_LANG com o valor
BRAZILIAN PORTUGUESE_BRAZIL.UTF8 antes que o código da biblioteca seja carregado.
Mais informações oficiais sobre a variável aqui
e aqui.
De acordo com a documentação oficial, essa variável não especifica apenas 1,
mas 3 valores: LINGUAGEM_TERRITÓRIO.CHARSET. No meu caso, portanto,
foram especificados:
- LINGUAGEM:
BRAZILIAN PORTUGUESE - TERRITÓRIO:
BRAZIL - CHARSET:
UTF8
Note que, para a minha aplicação web, apenas o CHARSET é relevante. Até
onde li na documentação, LINGUAGEM e TERRITÓRIO servem mais para indicar
ao Oracle como ele deve exibir mensagens de erro ou formatar datas para
apresentação. CHARSET parece indicar ao Oracle que faça uma conversão
entre o charset real do banco de dados e o valor do charset especificado
em NLS_LANG no momento da leitura de dados. Portanto, os dados continuam sendo armazenados com o charset original,
mas quando o Rails solicita esses dados a partir da biblioteca oci8, o Oracle os
converte para UTF-8 (neste caso) e depois os entrega. Essa parece ser uma
boa explicação para o correto funcionamento da aplicação após a definição
dessa variável, mas o problema que relato ao fim do artigo mostra que,
na prática, a teoria é outra.
Testei duas maneiras de definir essa variável. A primeira é colocar a seguinte linha no arquivo ~/.bashrc do usuário no qual o servidor de aplicação roda:
export NLS_LANG='BRAZILIAN PORTUGUESE_BRAZIL.UTF8'
Mas acho mais interessante embutir essa declaração dentro do próprio código
da aplicação. Não sei qual o local mais apropriado para isso, mas inserir
esta linha no início do arquivo config/environment.rb funcionou:
ENV['NLS_LANG']='BRAZILIAN PORTUGUESE_BRAZIL.UTF8'
Essa solução resolveu o problema completamente? Não. Para textos inseridos a partir da aplicação web, caracteres acentuados são gravados no banco de dados e lidos da forma correta (não são substituídos por um ou dois sinais de interrogação). Mas essa solução estava simples demais para ser verdade, certo?
Como estou desenvolvendo a aplicação web sobre um banco de dados já existente, e que já possui dados, rodei o servidor de aplicação em modo de produção para ver se os dados já existentes eram apresentados corretamente também. Resultado: problemas de acentuação novamente. Os caracteres acentuados lidos do banco de dados são trocados por pontos de interrogação.
Fica a seu critério, portanto, decidir se esta solução é suficiente pra você. Até o momento acredito que ela seja suficiente pra mim, então não pretendo perder mais tempo com isso. Caso eu tenha algum problema decorrente da utilização dessa variável de ambiente, escreverei sobre isso aqui no blog.

October 15th, 2008 às 6:08 pm
Otima dica, muito obrigado, me ajudou muito.. e nem tive o problema aí mencionado, utilizei até com dados do ja gravados no banco e funcionou.. valeuu..
October 22nd, 2008 às 4:17 pm
Valeu pela dica, era justamente o que eu precisava!