valid_encoding? の validation 作成
validates_each だと allow_blank オプションのチェックの関係で String#blank? が呼ばれてその中で「ArgumentError: invalid byte sequence」になってしまうので使えなかった。
blank? で ArgumentError になるのは直る予定はなさそうなので、 validates_each は使えなさそうだった。 (参考: https://github.com/rails/rails/issues/1532 )
どうにか回避出来ないかいろいろがんばってみたところ validates_with なら大丈夫だった。
たとえば
- rails new invalid-byte-sequence -T
- cd invalid-byte-sequence
- rails g scaffold post title
- rake db:migrate
のように作成した rails 3.2.2 のアプリケーションで、以下のように validation を設定するとうまくいった。
- rails runner 'Post.create!(title: "\x82\xA0")'
などで動作確認出来る。("\x82\xA0" は "\u3042".encode(Encoding::SJIS).force_encoding(Encoding::UTF_8)) で作成)
コメントアウトしている部分を有効にしたり、他の validates に「if: "title.valid_encoding?"」をつけていなかったりすると「invalid byte sequence in UTF-8」になる。
class EncodingValidator < ActiveModel::Validator def validate(record) unless record.title.valid_encoding? record.errors[:title] << "has invalid encoding" end end end class Post < ActiveRecord::Base validates :title, presence: true, if: "title.valid_encoding?" #validates_each :title do |record, attr, value| #end validates_with EncodingValidator end