Ruby 1.9, Rails и invalid byte sequence in US-ASCII
24 ноября 2011, 00:54
Готов поспорить, если у вас есть legacy-проект на Rails 2.3, в котором до сих пор используется версия ruby 1.8.7, то не раз была попытка перехода на 1.9, в погоне за новыми возможностями и ускорением работы приложения :)
И раз проект все еще на 1.8.7..
Обычно, проблемы возникают с кодировками: русскими текстами, записанными в .erb, или строками на русском языке, возвращаемыми из MySQL.
Возникающие ошибки проявляются в виде сообщений типа:
В Интернете довольно много разношерстных решений данной проблемы. Попытаюсь собрать их в одном месте.
Эти способы нашим проектам - помогли. Надеюсь и вашим тоже :) Удачи!
И раз проект все еще на 1.8.7..
Обычно, проблемы возникают с кодировками: русскими текстами, записанными в .erb, или строками на русском языке, возвращаемыми из MySQL.
Возникающие ошибки проявляются в виде сообщений типа:
invalid byte sequence in US-ASCII
или:
incompatible character encodings: UTF-8 and ASCII-8BIT.
В Интернете довольно много разношерстных решений данной проблемы. Попытаюсь собрать их в одном месте.
environment.rb
В самое начало необходимо вставить такие строчки кода:
Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::UTF_8
Подробнее можно почитать по этой ссылке: http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings. Там объясняется смысл этих строк.
Encoding.default_external = Encoding::UTF_8
config/initializers/patches.rb
# Patching MySQL:
#
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
# Patching ActionController:
#
module ActionController
class Request
private
def normalize_parameters_with_force_encoding(value)
(_value = normalize_parameters_without_force_encoding(value)).respond_to?(:force_encoding) ?
_value.force_encoding(Encoding::UTF_8) : _value
end
alias_method_chain :normalize_parameters, :force_encoding
end
end
Данный код делает примерно то же самое, но специально для MySQL и ActionController.
#
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
# Patching ActionController:
#
module ActionController
class Request
private
def normalize_parameters_with_force_encoding(value)
(_value = normalize_parameters_without_force_encoding(value)).respond_to?(:force_encoding) ?
_value.force_encoding(Encoding::UTF_8) : _value
end
alias_method_chain :normalize_parameters, :force_encoding
end
end
Эти способы нашим проектам - помогли. Надеюсь и вашим тоже :) Удачи!
Размещено в категории: ruby and rails
