ruby-on-rails - Active Record 序列化 attr 丢失字符串编码(可能是 YAML 问题),解决方法?

标签 ruby-on-rails ruby activerecord yaml

我在使用 Rails 2.3.8 和 Ruby 1.9.1 时遇到问题 事件记录中的序列化属性不保留字符串编码。 潜在的问题可能是yaml,但我想知道是否有人有 关于如何处理这个的任何好主意。我正在开发的应用程序有 许多序列化字段,其中一些包含深层结构 数组和哈希。取回一个 ASCII-8 位字符串(实际上是 UTF-8) 在这些结构的深处会在以后造成严重破坏......

也许最好用例子来说明,如果我将 l 保存到一个序列化的属性中 一个事件记录模型,我会在从数据库中读取数据时返回 l2。

>> l
=> ["English", "Türkçe", "Русский"]
>> l.map(&:encoding)
=> [#<Encoding:UTF-8>, #<Encoding:UTF-8>, #<Encoding:UTF-8>]
>> l.map(&:valid_encoding?)
=> [true, true, true]
>> l.to_yaml
=> "--- \n- English\n- !binary |\n  VMO8cmvDp2U=\n\n-
\"\\xD0\\xA0\\xD1\\x83\\xD1\\x81\\xD1\\x81\\xD0\\xBA\\xD0\\xB8\\xD0\\xB9\"\n"
>> l2 = YAML.load(l.to_yaml)
=> ["English", "T\xC3\xBCrk\xC3\xA7e", "Русский"]
>> l2.map(&:encoding)
=> [#<Encoding:UTF-8>, #<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>]

有谁知道 yaml 如何决定是否将字符串存储为 二进制与作为转义字符串?上面的最后两个字符串都是 非 ascii-7 但只有第一个存储为二进制...

我目前的想法是 Hook 事件记录反序列化例程,遍历哈希和数组并强制对所有字符串元素进行编码。不是非常安全或一般,但可能适用于我的用例,但我也想知道是否有人修补 YAML 在这里变得更聪明......

最佳答案

我确实想出了一个解决方案:

猴子修补字符串可以强制 YAML 使用\转义而不是二进制,因此以默认编码(对我来说是 UTF-8)而不是 ASCII-8BIT 返回字符串

class String
  def is_binary_data?
    encoding == Encoding::ASCII_8BIT unless empty?
  end
end

最初这个例程使用一些启发式算法,这些算法会更短\转义字符串的二进制编码,这就是为什么我只有一些国际字符串有问题。

关于ruby-on-rails - Active Record 序列化 attr 丢失字符串编码(可能是 YAML 问题),解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3630702/

相关文章:

ruby-on-rails - Rails 参数未传递给 'params' 变量

ruby-on-rails - string % 4 -> 在 ruby​​ 中是什么

ruby-on-rails - 没有 has_many 关联元素的 Rails 作用域过滤元素

ruby-on-rails - 事件管理员 : Customize only new form

ruby-on-rails - 将两个 ActiveRecord::Relation 与 OR 组合,而不是 AND,返回一个 Relation 而不是一个 Array 以便以后能够分页

ruby-on-rails - 访问范围内的父级

ruby - Ruby 中的数组哈希

ruby - Ruby 中的 Splat 运算符(快速排序示例)

ruby-on-rails - Rails 4 x postgresql:ActiveRecord::InvalidForeignKey

mysql - 使用 like 与代码点火器事件记录连接