ActiveRecord(Ruby on Rails)とMySQLで大文字と小文字を区別する方法

はじめに

この記事は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であれば別値と判定されるので複数レコード保存が出来てしまうのです。

知らないと混乱してしまうかも知れません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA