"Incorrect string value" 尝试将 UTF-8 从 Rails 插入 MySQL 时
"Incorrect string value" when trying to insert UTF-8 into MySQL from Rails
调试我的 Rails 应用程序时,我在日志文件中发现以下消息:
(0.1ms) ROLLBACK
Completed 500 Internal Server Error in 25ms (ActiveRecord: 4.2ms)
ActiveRecord::StatementInvalid (Mysql2::Error: Incorrect string value: '\xF0\x9F\x98\x89 u...' for column 'description' at row 1: INSERT INTO `course` (`title`, `description`) VALUES ('sometitle', '<p>Description containing and stuff</p>')
这似乎是因为我的数据库是 MySQL with not-quite-utf-8:
CREATE TABLE `course` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(250) DEFAULT NULL,
`description` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2080 DEFAULT CHARSET=utf8;
根据 the answers to this question CHARSET=utf8 只能处理 3 字节字符,不能处理 4 字节字符。
表情符号需要四个字节 - 请参阅日志文件中的 \xF0\x9F\x98\x89。
我对转换整个数据库持谨慎态度。我宁愿禁止使用表情符号和其他 4 字节字符 - 它们在我的网站上真的没有必要。
在 Rails 中执行此操作的最佳方法是什么?
基于 regular expressions from these answers 我实现了一个验证器:
# file /lib/three_byte_validator.rb
# forbid characters that use more than three byte
class ThreeByteValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value =~ /[\u{10000}-\u{10FFFF}]/
record.errors.add attribute, (options[:message] || 'Keine Emoticons, keine UTF-8 Zeichen mit 4 Byte')
end
end
end
现在我可以在最先出现问题的模型上使用这个验证器了:
class Course < ApplicationRecord
validates :title, length: { in: 3..100 }, three_byte: true
validates :description, length: { minimum: 50 }, three_byte: true
以及其他型号:
class Person < ApplicationRecord
validates :firstname, :lastname, :country, :city, :address, three_byte: true
在 MySQL 中,眨眼脸(和大多数其他表情符号)需要 utf8mb4
而不是 utf8
。
调试我的 Rails 应用程序时,我在日志文件中发现以下消息:
(0.1ms) ROLLBACK
Completed 500 Internal Server Error in 25ms (ActiveRecord: 4.2ms)
ActiveRecord::StatementInvalid (Mysql2::Error: Incorrect string value: '\xF0\x9F\x98\x89 u...' for column 'description' at row 1: INSERT INTO `course` (`title`, `description`) VALUES ('sometitle', '<p>Description containing and stuff</p>')
这似乎是因为我的数据库是 MySQL with not-quite-utf-8:
CREATE TABLE `course` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(250) DEFAULT NULL,
`description` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2080 DEFAULT CHARSET=utf8;
根据 the answers to this question CHARSET=utf8 只能处理 3 字节字符,不能处理 4 字节字符。
表情符号需要四个字节 - 请参阅日志文件中的 \xF0\x9F\x98\x89。
我对转换整个数据库持谨慎态度。我宁愿禁止使用表情符号和其他 4 字节字符 - 它们在我的网站上真的没有必要。
在 Rails 中执行此操作的最佳方法是什么?
基于 regular expressions from these answers 我实现了一个验证器:
# file /lib/three_byte_validator.rb
# forbid characters that use more than three byte
class ThreeByteValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value =~ /[\u{10000}-\u{10FFFF}]/
record.errors.add attribute, (options[:message] || 'Keine Emoticons, keine UTF-8 Zeichen mit 4 Byte')
end
end
end
现在我可以在最先出现问题的模型上使用这个验证器了:
class Course < ApplicationRecord
validates :title, length: { in: 3..100 }, three_byte: true
validates :description, length: { minimum: 50 }, three_byte: true
以及其他型号:
class Person < ApplicationRecord
validates :firstname, :lastname, :country, :city, :address, three_byte: true
在 MySQL 中,眨眼脸(和大多数其他表情符号)需要 utf8mb4
而不是 utf8
。