如何验证字符串属性,避免出现“ ActiveRecord :: StatementInvalid:Mysql2 :: Error:数据对于列[...]而言过长”的异常?

Mar*_*req 5 mysql ruby-on-rails ruby-on-rails-4

我面临与包含UTF-8字符的字符串属性相关的MySQL文本列的问题。假设我们进行了这样的迁移:

class CreateItems < ActiveRecord::Migration
  def change
    create :items do |t|
      t.text "description", null: false
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我们知道该MySQL TEXT列的最大长度为65535字节,并且在下面添加这样的验证应该可以防止此类MySQL异常:

class Item < ActiveRecord::Base
  validates :description, length: { maximum: 65535 }
end
Run Code Online (Sandbox Code Playgroud)

当然,直到用户放置包含一些超过1个字节长的字符的非常长的文本时,它才起作用。有什么区别?参见示例:

> s = "A text with some national characters ????"          
=> "A text with some national characters ????"
> s.length
=> 41
> s.bytesize
=> 45
Run Code Online (Sandbox Code Playgroud)

因此,例如,如果有人将长说明65500个字符长了很多这样的字符,则验证通过了它,但MySQL不会原谅...

我暂时创建了一个bytesize验证:

class BytesizeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors.add(attribute, :too_long, count: options[:maximum]) if value.bytesize > options[:maximum]
  end
end
Run Code Online (Sandbox Code Playgroud)

该模型中使用的方法如下:

validates :description, bytesize: { maximum: 65535 }
Run Code Online (Sandbox Code Playgroud)

解决了我的问题,但我相信,有一个简单的解决方案。也许我错过了一些东西,并且可以length validation按预期在常规Rails中覆盖多字节字符吗?

我在Linux上使用Rails 4.2.5.1,Ruby 2.2.4和MariaDB 15.1。