Могу ли я установить кодировку строк по умолчанию в Ruby 1.9?

Это может показаться незначительным, но это сводило меня с ума. С момента выпуска приложения в рабочую среду в прошлую пятницу на Ruby 1.9 у меня было много мелких исключений, связанных с кодировками символов. Почти все это является некоторыми вариациями на тему:

Encoding::CompatibilityError: incompatible character encodings: ASCII-8BIT and UTF-8

У нас есть международная база пользователей, поэтому многие имена содержат умлауты и т. д. Если я исправлю шаблоны для использования force_encoding в нескольких местах, он появится во всплывающем помощнике по сообщениям. И так далее.

На данный момент похоже, что я прибил все, о чем знал, исправив конкатенацию строк ActiveSupport в одном месте, а затем установив # encoding: utf-8 в начале каждого из моих исходных файлов. Но ощущение, что мне, возможно, придется помнить об этом для каждого файла каждого проекта Ruby, который я когда-либо буду делать с этого момента, навсегда, просто чтобы избежать проблем с назначением строк, не устраивает меня в желудке. Я читал о переключателе -Ku, но все, кажется, предупреждают, что это для обратной совместимости и может исчезнуть в любое время.

Итак, мой вопрос к опытным в 1.9 людям: действительно необходимо ли устанавливать #encoding в каждом из моих файлов? Есть ли разумный способ сделать это глобально? Или, лучше, способ установить кодировку по умолчанию для небуквенных значений строк, которые обходят внутренние/внешние значения по умолчанию?

Спасибо заранее за любые предложения.


person SFEley    schedule 19.01.2010    source источник


Ответы (4)


Не путайте кодировку файла с кодировкой строки

Цель оператора #encoding в верхней части файлов — дать знать Ruby во время чтения/интерпретации вашего кода, а вашему редактору знать, как обрабатывать любые символы, отличные от ASCII, при редактировании/чтении файла -- это необходимо только в том случае, если в файле есть хотя бы один символ, отличный от ASCII. например это необходимо в ваших файлах конфигурации/локали.

Чтобы определить кодировку сразу во всех ваших файлах, вы можете использовать magic_encoding gem, он может вставлять магический комментарий uft-8 во все файлы ruby ​​в вашем приложении.

Ошибка, которую вы получаете во время выполнения Encoding::CompatibilityError, возникает, когда вы пытаетесь объединить две строки с разными кодировками во время выполнения программы, и их кодировки несовместимы.

Это чаще всего происходит, когда:

  • вы используете строки L10N (например, UTF-8) и объединяете их, например, Строка ASCII (на ваш взгляд)

  • пользователь вводит строку на иностранном языке (например, UTF-8), и ваше представление пытается распечатать ее в каком-либо представлении вместе с некоторой фиксированной строкой, которую вы предварительно определили (ASCII). force_encoding поможет в этом. В Rails 1.9 также есть Encoding::primary_encoding для установки кодировки по умолчанию для новых строк. И в Rails есть config.encoding в файле config/application.rb.

  • Строка, которая поступает из вашей базы данных, а затем объединяется с другими строками в вашем представлении. (их кодировки могут быть разными и несовместимыми).

Примечание: Обязательно укажите кодировку по умолчанию при создании базы данных!

    create database yourproject  DEFAULT CHARACTER SET utf8;

Если вы хотите использовать EMOJI в своих строках:

    create database yourproject DEFAULT CHARACTER SET utf8mb4 collate utf8mb4_bin;

и все индексы строковых столбцов, которые могут содержать EMOJI, должны иметь длину 191 символ. НАБОР СИМВОЛОВ utf8mb4 РАЗБОР utf8mb4_bin

Причина этого в том, что обычный UTF8 использует до 3 байтов, тогда как EMOJI использует 4 байта для хранения.

Пожалуйста, ознакомьтесь со статьей Иегуды Каца, в которой это подробно рассматривается и очень хорошо объясняется: (в частности, есть раздел «Несовместимые кодировки»)

http://yehudakatz.com/2010/05/05/ruby-1-9-encodings-a-primer-and-the-solution-for-rails/

http://yehudakatz.com/2010/05/17/encodings-unabridged/< /а>

и:

http://zargony.com/2009/07/24/ruby-1-9-and-file-encodings

http://graysoftinc.com/character-encodings

person Tilo    schedule 18.10.2011
comment
Я не хочу разбираться со всей этой кутерьмой кодирования, приятно знать все пограничные случаи, но хотелось бы там, где нет пограничных случаев. Просто относитесь ко всему как к utf8, и если что-то является чем-то другим, оно должно быть объявлено как таковое. - person grosser; 19.10.2011
comment
@grosser: я согласен - это огромная боль! и что еще хуже, из-за этого они испортили классы ввода-вывода нижнего уровня, которые раньше возвращали строки из 8-битных байтов.. теперь они возвращают интерпретированные строки «кто знает что» - супер раздражает, если вам нужно иметь дело с неинтерпретированным сырые байты.. - person Tilo; 19.10.2011
comment
@grosser - давайте будем честными. До появления UTF8 Японии приходилось обходиться самостоятельно. Благодаря тому, что Ruby является тем, чем он является в Японии, и присутствию ISO-2022-JP и Shift_JIS, так оно и будет. Если вы хотите быть НАСТОЯЩИМ пуристом, все еще есть НЕКОТОРЫЕ символы, которые также не кодируются в UTF-8. Но в целом я с вами АБСОЛЮТНО согласен, мы все должны использовать UTF8 и покончить с этим. - person makdad; 29.05.2012

В вашем config/application.rb добавьте

config.encoding = "utf-8"

и над строкой Application.initialize! в config/environment.rb добавьте следующие две строки:

Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8

Надеюсь это поможет.

person nathanvda    schedule 17.10.2011
comment
выглядят многообещающе, но все еще получают те же старые многобайтовые ошибки, когда, например. загрузить «xxx.rb», где xxx.rb содержит utf8 - person grosser; 17.10.2011
comment
config.encoding предназначен для кодирования вывода html rails afaik, ничего общего с кодировкой строки ruby - person grosser; 18.10.2011
comment
В этом ответе также делается предположение (хотя и справедливо), что ОП спрашивает о Rails. - person makdad; 29.05.2012

http://zargony.com/2009/07/24/ruby-1-9-and-file-encodings

Не путайте кодировку файла и кодировку строки!

person Trevoke    schedule 19.01.2010
comment
Спасибо, Тревок; Я знаю разницу. Однако строки наследуют кодировку исходного файла, в котором они созданы. (Если только они не получены из операции ввода-вывода в другом файле; отсюда и свойства default_internal и default_external.) Таким образом, хотя они и не одинаковы, они глубоко и разочаровывающе связаны. Мне нужен способ установить кодировку string по умолчанию без использования этого комментария #encoding. - person SFEley; 19.01.2010
comment
Все, что вы когда-либо хотели знать о кодировках: blog.grayproductions.net/categories/character_encodings И, возможно, многое другое, что вы надеялись никогда не узнать :) - person Trevoke; 19.01.2010

String.module_eval "def initialize\nsuper\nputs encoding\nend"
=> nil
irb(main):006:0> String.new
ASCII-8BIT
=> ""

Не знаю, как реализовать ваши строки в вашей системе, но подключившись к методу инициализации объекта String, вы можете установить кодировку для любых строк, которые вы создаете во всем приложении.

person Shayne Wheeler    schedule 16.10.2011
comment
похоже, не исправляет загрузку файлов с помощью utf8. Я пробовал: String.module_eval def initialize\nsuper\nencoding = Encoding::UTF_8\nend load 'xxx.rb' - person grosser; 17.10.2011
comment
Проведя еще немного тестов, я заметил, что метод инициализации для строк вызывается редко. Но это было просто предложение, может быть, есть метод для всех строк, которые вы вызываете, когда создаете их в своем приложении? Просто добавьте к этому строку кодировки вместо инициализации. (и под созданием я подразумеваю загрузку в память, синтаксический анализ или что-то еще) - person Shayne Wheeler; 19.10.2011
comment
возможно, перезапись require могла бы помочь, но я не хочу заходить так далеко: D - person grosser; 19.10.2011