ActionView :: Template :: Error (несовместимые кодировки символов: UTF-8 и ASCII-8BIT) - PullRequest
15 голосов
/ 07 марта 2011

Я использую Ruby 1.9.2, Rails 3.0.4 / 3.0.5 и Phusion Passenger 3.0.3 / 3.0.4. Мои шаблоны написаны на HAML, и я использую гем MySQL2. У меня есть действие контроллера, которое при передаче параметра, имеющего специальный символ, например, умляут, выдает мне следующую ошибку:

ActionView::Template::Error (incompatible character encodings: UTF-8 and ASCII-8BIT)

Ошибка указывает на первую строку моего шаблона HAML, в которой указан следующий код:

<!DOCTYPE html>

Насколько я понимаю, это вызвано тем, что у меня есть строка UTF-8, которая соединяется со строкой ASCII-8BIT, но я не могу понять, что это за строка ASCII-8BIT. Я проверил, что параметры в действии кодируются с использованием UTF-8, и я добавил кодировку: объявление UTF-8 в начало шаблона HAML и файлы ruby, и я все еще получаю эту ошибку. Мой файл application.rb также содержит декларацию config.encoding = "UTF-8", и следующие результаты приводят к UTF-8:

ENV['LANG']
__ENCODING__
Encoding.default_internal
Encoding.default_external

Вот кикер: я не могу воспроизвести этот результат локально на моем Mac-OSX, используя автономного пассажира или дворнягу в процессе разработки или производства. Я могу воспроизвести его только на производственном сервере под управлением nginx + passenger на linux. В консоли рабочего сервера я проверил, что все упомянутые выше команды также приводят к UTF-8.

Испытывали ли вы эту же ошибку и как ее решили?

Ответы [ 2 ]

12 голосов
/ 09 марта 2011

После некоторой отладки я обнаружил, что проблема возникает при использовании объекта ActionDispatch :: Request, в котором есть строки, все они закодированы в ASCII-8BIT, независимо от того, кодировано ли мое приложение в UTF-8 или нет. Я не знаю, почему это происходит только при использовании производственного сервера в Linux, но я собираюсь предположить, что это какая-то особенность в Ruby или Rails, так как я не смог воспроизвести эту ошибку локально. Ошибка произошла именно из-за такой строки:

@current_path = request.env['PATH_INFO']

Когда эта переменная экземпляра была напечатана в шаблоне HAML, это вызвало ошибку, потому что строка была закодирована в ASCII-8BIT вместо UTF-8. Чтобы решить эту проблему, я сделал следующее:

@current_path = request.env['PATH_INFO'].dup.force_encoding(Encoding::UTF_8)

Что заставило @current_path использовать дублированную строку, которая была принудительно введена в правильную кодировку UTF-8. Эта ошибка также может возникать с другими данными, связанными с запросом, такими как request.headers.

9 голосов
/ 08 марта 2011

Mysql может быть источником проблемной ASCII.Попробуйте добавить следующее в инициализатор, чтобы хотя бы устранить эту возможность:

require 'mysql'

class Mysql::Result
  def encode(value, encoding = "utf-8")
    String === value ? value.force_encoding(encoding) : value
  end

  def each_utf8(&block)
    each_orig do |row|
      yield row.map {|col| encode(col) }
    end
  end
  alias each_orig each
  alias each each_utf8

  def each_hash_utf8(&block)
    each_hash_orig do |row|
      row.each {|k, v| row[k] = encode(v) }
      yield(row)
    end
  end
  alias each_hash_orig each_hash
  alias each_hash each_hash_utf8
end



edit

Это может быть неприменимо к mysql2 gem.Работает для MySQL, однако.

...