はじめに
この記事はRuby on RailsにてActiveRecordを、DBにMySQLを使用している方向けの記事になります。
大文字と小文字を区別するには
カラムに対してユニーク制約を掛ける時に大文字と小文字を区別したい時があります。つまり「HOGE」と「hoge」は別物として保存したいということです。
この際に運用のことを考えている方だったらActiveRecordのValidationをどうしようかと悩むかと思います。
しかし、DBにMySQLを採用している場合は元から大文字・小文字を区別しない文字コードが設定されているのでいくらRailsで区別するような設定を追加しても、DBの方には同じ文字列と判定されてしまうので、そもそも保存することが出来ません。
ですから大文字・小文字を区別してDBに保存したい場合はまず、MySQLで設定を行ってからActiveRecordのValidationを考えます。
マイグレーションの作り方
既にUsersテーブルが存在していて、そこにnameカラムを追加して大文字・小文字を区別するユニーク制約を付与するマイグレーションを書いてみます。
class AddNameToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :name, :string
add_index :users, unique: true
end
end
class ChangeNameToSites < ActiveRecord::Migration[6.0]
def up
execute('ALTER TABLE users MODIFY name varchar (255) BINARY;')
end
def down
execute('ALTER TABLE users MODIFY name varchar (255);')
end
end
カラムにBINARY属性を付与すると大文字・小文字を区別する文字コードに変わります。
execute()
メソッドはchange
の中に記述してもRailsが自動でロールバック処理を生成してくれないので、自分でdown
の中にロールバック処理を記述しています。
バリデーション
バリデーションは書くとするならざっと下記の様なところでしょうか。
class User < ApplicationRecord
validates :name, format: { with: %r{\A/[0-9a-zA-Z]+\z}, allow_nil: true,
uniqueness: { case_sensitive: true } }
end
英数字のみを許可、大文字・小文字を区別するユニーク制約を掛けています。加えてNULLも許可していますが深い意味はありません。
以上が大文字・小文字を区別するユニーク制約を掛けたカラムの追加方法です。
NULLとユニーク制約
ちなみにNULLがユニーク制約の対象にならないのはご存知でしたでしょうか。つまりユニーク制約を掛けていてもNULLであれば別値と判定されるので複数レコード保存が出来てしまうのです。
知らないと混乱してしまうかも知れません。