在 Rails 中保存后向属性添加了奇怪的字节
Weird Bytes Added to Attribute After Save in Rails
我们遇到了一个疯狂的错误,在保存电子邮件时,大约 90% 的时间看似随机的字节被附加到电子邮件字段。以下是可能发生的情况的示例:
来自参数:'user@example.com'
验证前:'user@example.com'
验证后:'user@example.com'
保存前:'user@example.com'
保存后对象中的值:'user@example.com'
检索刚刚由id创建的记录,并获取id:'user@example.com\u007f'
\u007f
(UTF-8 delete character!!!)到底从哪里来的?!这是迄今为止出现的最常见的垃圾。下面是一些其他不时出现的有效字节序列的列表:
r\u007f
U\u007f
a\u007f
#m$\u007f
有时我得到的都是垃圾位,由于 PG::CharacterNotInRepertoire
错误,我无法判断是否有比这些更多的字节:
0xde 0x4d
0xf6 0x7f
0xbc
0xe3 0x6c 0x24
考虑到发生的 PG::CharacterNotInRepertoire
错误,我假设这发生在值被保存之前的某处,但超出了我的应用程序代码的范围。
请注意,奇怪的是,用户的任何其他字段都没有发生这种情况。
以下是当前接触电子邮件地址的所有回调:
#strip!
和 #downcase!
验证前
- 使用正则表达式进行格式验证
\A[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,20}\z
一些应用信息:
- Ruby v2.2.0
- Rails v4.1.8
- Postgres v9.3.2
- PG v0.17.1
事实证明 pg-ruby
< v0.18.0 与 Ruby v2.2 不兼容,尽管没有明显的相反警告...
https://bitbucket.org/ged/ruby-pg/issue/210/crazy-bytes-being-added-to-record
立即升级或获取位。
另请注意,如果您使用的是 Rails 4.2.0,则 pg 0.18.* 存在一个影响写入二进制数据的问题。我目前有 4.2.0 monkey-patched 补丁将在 4.2.1 中。如果您是 运行 4.2.0 和 Ruby 2.2(因此是 pg 0.18.),请参阅 https://github.com/rails/rails/pull/17680 了解详细信息。 Rails 4.0. 和 4.1.* 上可能有类似的问题 - 我还没有弄清楚哪个版本有补丁,以及那些版本是否已经发布。
我的 4.2.0 猴子补丁看起来像:
# Should release in Rails 4.2.1
# PostgreSQL, Fix change detection caused by superfluous bytea unescaping
# See https://github.com/rails/rails/pull/17680
if Rails.version == '4.2.0'
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Bytea < Type::Binary # :nodoc:
def type_cast_from_database(value)
return if value.nil?
return value.to_s if value.is_a?(Type::Binary::Data)
PGconn.unescape_bytea(super)
end
end
end
end
end
end
end
我们遇到了一个疯狂的错误,在保存电子邮件时,大约 90% 的时间看似随机的字节被附加到电子邮件字段。以下是可能发生的情况的示例:
来自参数:'user@example.com' 验证前:'user@example.com' 验证后:'user@example.com' 保存前:'user@example.com' 保存后对象中的值:'user@example.com' 检索刚刚由id创建的记录,并获取id:'user@example.com\u007f'
\u007f
(UTF-8 delete character!!!)到底从哪里来的?!这是迄今为止出现的最常见的垃圾。下面是一些其他不时出现的有效字节序列的列表:
r\u007f U\u007f a\u007f #m$\u007f
有时我得到的都是垃圾位,由于 PG::CharacterNotInRepertoire
错误,我无法判断是否有比这些更多的字节:
0xde 0x4d
0xf6 0x7f
0xbc
0xe3 0x6c 0x24
考虑到发生的 PG::CharacterNotInRepertoire
错误,我假设这发生在值被保存之前的某处,但超出了我的应用程序代码的范围。
请注意,奇怪的是,用户的任何其他字段都没有发生这种情况。
以下是当前接触电子邮件地址的所有回调:
#strip!
和#downcase!
验证前- 使用正则表达式进行格式验证
\A[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,20}\z
一些应用信息:
- Ruby v2.2.0
- Rails v4.1.8
- Postgres v9.3.2
- PG v0.17.1
事实证明 pg-ruby
< v0.18.0 与 Ruby v2.2 不兼容,尽管没有明显的相反警告...
https://bitbucket.org/ged/ruby-pg/issue/210/crazy-bytes-being-added-to-record
立即升级或获取位。
另请注意,如果您使用的是 Rails 4.2.0,则 pg 0.18.* 存在一个影响写入二进制数据的问题。我目前有 4.2.0 monkey-patched 补丁将在 4.2.1 中。如果您是 运行 4.2.0 和 Ruby 2.2(因此是 pg 0.18.),请参阅 https://github.com/rails/rails/pull/17680 了解详细信息。 Rails 4.0. 和 4.1.* 上可能有类似的问题 - 我还没有弄清楚哪个版本有补丁,以及那些版本是否已经发布。
我的 4.2.0 猴子补丁看起来像:
# Should release in Rails 4.2.1
# PostgreSQL, Fix change detection caused by superfluous bytea unescaping
# See https://github.com/rails/rails/pull/17680
if Rails.version == '4.2.0'
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Bytea < Type::Binary # :nodoc:
def type_cast_from_database(value)
return if value.nil?
return value.to_s if value.is_a?(Type::Binary::Data)
PGconn.unescape_bytea(super)
end
end
end
end
end
end
end