Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
148
Help us understand the problem. What is going on with this article?

More than 5 years have passed since last update.

@kamipo

ActiveRecordでデフォルトの照合順序を変更する

MySQLには文字列の照合順序(collation)というのがあって、MySQL側でのcharset utf8のときのデフォルトの照合順序はutf8_general_ciです。

ActiveRecord::Migrationでは明示的に照合順序を指定しない場合、charset utf8で照合順序utf8_unicode_ciのデータベースを作成しますが、これは少なくとも日本語圏では多くの人が期待する挙動ではないと思われるので注意が必要です。

たとえば、以下のようなファミリーテーブルをrake db:migrateすると

db/migrate/20121112110702_create_families.rb
# coding: utf-8
class CreateFamilies < ActiveRecord::Migration
  def change
    create_table :families do |t| 
      t.string :name
      t.string :relationship
    end 
    # add_index :families, :relationship, unique: true
    Family.create(name: 'ユイ',   relationship: '本人')
    Family.create(name: 'キリト', relationship: 'パパ')
    Family.create(name: 'アスナ', relationship: 'ハハ')
  end 
end

utf8_unicode_ciなテーブルが作成されます。

CREATE TABLE `families` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `relationship` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
SELECT * FROM families;
+----+-----------+--------------+
| id | name      | relationship |
+----+-----------+--------------+
|  1 | ユイ      | 本人         |
|  2 | キリト    | パパ         |
|  3 | アスナ    | ハハ         |
+----+-----------+--------------+

ここで'パパ'を検索すると、utf8_unicode_ciでは'ハ'と'パ'は等価と扱われるので'ハハ'も検索に引っかかります。この挙動を期待するケースはあまり多くないのではないでしょうか。

SELECT * FROM families WHERE relationship = 'パパ';
+----+-----------+--------------+
| id | name      | relationship |
+----+-----------+--------------+
|  2 | キリト    | パパ         |
|  3 | アスナ    | ハハ         |
+----+-----------+--------------+

また、relationshipカラムにUNIQUEインデックスを張ってあると'パパ'と'ハハ'がUNIQUE制約を満たせないので以下のようにエラーになります。

Mysql2::Error: Duplicate entry 'ハハ' for key 'relationship': INSERT INTO `families` (`name`, `relationship`) VALUES ('アスナ', 'ハハ')

ということで、照合順序utf8_general_ciなデータベースを作成したいわけですが、これはコンフィグでcharsetcollationを指定するだけで簡単にいけます。

config/database.yml
development:
  adapter: mysql2
  encoding: utf8
  charset: utf8
  collation: utf8_general_ci
  reconnect: false
  database: sao_development

これでrake db:migrateすると

CREATE TABLE `families` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `relationship` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `relationship` (`relationship`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

MySQL側のデフォルトの照合順序(utf8_general_ci)で作成されて

SELECT * FROM families WHERE relationship = 'パパ';
+----+-----------+--------------+
| id | name      | relationship |
+----+-----------+--------------+
|  2 | キリト    | パパ         |
+----+-----------+--------------+

ちゃんと'パパ'だけが検索に引っかかりました!

これで家族におばあちゃんが増えても安心ですね!!

148
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
148
Help us understand the problem. What is going on with this article?