我可以在Ruby 1.9上设置默认字符串编码吗?

时间:2010-01-19 17:30:32

标签: ruby-on-rails ruby utf-8 character-encoding ruby-1.9

这可能听起来很小,但它让我疯了。自上周五在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 个答案:

答案 0 :(得分: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来设置新字符串的默认编码。 在config / application.rb文件中的Rails中有config.encoding

  • 来自数据库的字符串,然后与视图中的其他字符串结合使用。 (他们的编码可以是两种方式,也可以是不相容的)。

Side-Note:确保在创建数据库时指定默认编码!

    create database yourproject  DEFAULT CHARACTER SET utf8;

如果您想在字符串中使用EMOJI:

    create database yourproject DEFAULT CHARACTER SET utf8mb4 collate utf8mb4_bin;

并且可能包含EMOJI的字符串列上的所有索引的长度必须为191个字符。字符集utf8mb4 COLLATE 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

答案 1 :(得分:6)

config/application.rb添加

config.encoding = "utf-8"

Application.initialize!的{​​{1}}行之上,添加以下两行:

config/environment.rb

希望这有帮助。

答案 2 :(得分:3)

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

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

答案 3 :(得分:-2)

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

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