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