Rails で、validates :name, uniqueness: true
にしているのに、
Duplicate Error
が出るケースに出会ったので書く。
(レースコンディションではないケース)
MySQL の文字列比較は、後続の空白を無視する
MySQL のすべての照合順序は、PADSPACE 型のものです。これは、MySQL 内のすべての CHAR、VARCHAR、および TEXT 値が、末尾のスペースに関係なく比較されることを意味します。
http://dev.mysql.com/doc/refman/5.6/ja/char.html
Ruby は文字列の空白を無視しない(ので、validation 発動しない)
class Person < ActiveRecord::Base
validates :name, uniqueness: true
end
person = Person.new(name: "一郎")
person.save
# => true
# 同名は false
person = Person.new(name: "一郎")
person.save
# => false
# 末尾に空白を入れると、Error になる
person = Person.new(name: "一郎 ")
person.save
# => ActiveRecord::RecordNotUnique: Mysql2::Error: Duplicate entry Error
対応方法
before_validation
で処理することにした。
class Person < ActiveRecord::Base
validates :name, uniqueness: true
before_validation -> { self.name.rstrip! }
end