17

这听起来可能微不足道,但它一直让我发疯。自从上周五在 Ruby 1.9 上将应用程序发布到生产环境以来,我遇到了很多与字符编码相关的小异常。几乎所有这些都是以下方面的一些变化:

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

我们有一个国际用户群,所以很多名字都包含变音符号等。如果我修复模板以在很多地方使用force_encoding,它会在 flash 消息帮助程序中弹出。等等。

目前看来,我已经确定了我所知道的所有内容,方法是在一个地方修补 ActiveSupport 的字符串连接,然后# encoding: utf-8在我的每个源文件的顶部进行设置。但是,从现在开始,为了避免字符串分配问题,我可能必须记住对我曾经做过的每个 Ruby 项目的每个文件都这样做,永远,这种感觉在我的胃​​里并不好。我阅读了有关-Ku开关的信息,但似乎一切都在警告它是为了向后兼容并且可能随时消失。

所以我对 1.9 有经验的人的问题是:#encoding在我的每个文件中进行设置真的有必要吗?有没有一种合理的方法可以在全球范围内做到这一点?或者,更好的方法是在绕过内部/外部默认值的字符串的非文字值上设置默认编码?

在此先感谢您的任何建议。

4

4 回答 4

13

不要将文件编码与字符串编码混淆

文件顶部的语句的目的#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.encodingconfig/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 个字节存储。

请查看这篇 Yehuda Katz 文章,该文章深入介绍了这一点,并很好地解释了它:(特别是“不兼容的编码”部分)

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

于 2011-10-18T17:35:56.640 回答
6

在你config/application.rb添加

config.encoding = "utf-8"

Application.initialize!在 中的行上方config/environment.rb,添加以下两行:

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

希望这可以帮助。

于 2011-10-17T07:14:25.427 回答
3

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

不要混淆文件编码和字符串编码!

于 2010-01-19T17:40:18.413 回答
-1
String.module_eval "def initialize\nsuper\nputs encoding\nend"
=> nil
irb(main):006:0> String.new
ASCII-8BIT
=> ""

不确定如何在系统中实现您的字符串,但通过挂钩 String 对象的初始化方法,您可以为您在整个应用程序中创建的任何字符串设置编码。

于 2011-10-16T18:22:31.073 回答