MySQLとバリデーションにおけるユニーク制約の違い
railsでアプリを作成していたところ、MySQLとvalidatesのユニーク制約で想定していなかった挙動をしました。
前提
内容
userテーブルを作成し、ユニーク制約をかけました。
$ rails g model User name:string
class CreateUser < ActiveRecord::Migration[6.0] def change create_table :users do |t| t.string :name, null: false t.timestamps end add_index :users, :name, unique: true # ユニーク制約追記 end end
$ rails db:migrate
class User < ApplicationRecord validates :name, presence: true validates :name, uniqueness: true end
一旦このバリデーションをかけました。
uniqueness: trueのバリデーションは大文字と小文字を区別するはずなので’aaaaaa’と’AAAAAA’というUserを試しにrails consoleで登録しようとしたところ、後者の登録時に、
ActiveRecord::RecordNotUnique: Mysql2::Error: Duplicate entry 'AAAAAA' for key 'index_users_on_name'
というエラーが発生しました。
解決策
どうやらMySQLでは大文字と小文字を区別しない、というのが標準の挙動だったようです。 今回は大文字と小文字を区別しない設計にしたかったのでバリデーションを変更します。
class User < ApplicationRecord validates :name, presence: true validates :name, uniqueness: true # case_sensitive: falseで大文字と小文字の区別をしなくなる end
このように書き換えたあと先ほどと同じUser名を登録しようとしたところ、バリデーションが利きROLLBACKされました。