読者です 読者をやめる 読者になる 読者になる

ウェブサービスを作っています。

MySQL の文字列で表記揺れを吸収しない

MySQL で、データベース・テーブル・カラムなどに collate = utf8_unicode_ci を指定すると、大文字・小文字・全角・半角・ひらがな・カタカナなどの表記揺れが吸収されます。
たとえば、「たろう」と「タロウ」の検索結果が同じになります。
参考: mysqlのcollateを使って大文字-小文字や全角-半角を無視した検索 - end0tknrのkipple - web写経開発


基本的には便利なのですが、厳密に区別したい (表記揺れを吸収したくない) ときもあります。
そんなときのために、ActiveRecord::ConnectionAdapters::MysqlAdapter#change_column_collation というメソッドを作りました。

module ActiveRecord
  module ConnectionAdapters
    class MysqlAdapter < AbstractAdapter
      def change_column_collation(table_name, column_name, collation)
        options = {}
        column = column_for(table_name, column_name)
        options[:default] = column.default
        options[:null] = column.null
        change_column_sql = "ALTER TABLE #{ quote_table_name(table_name) } MODIFY #{ quote_column_name(column_name) } " +
          "#{ column.sql_type } CHARACTER SET utf8"
        change_column_sql << " COLLATE #{ collation }" if collation
        add_column_options! change_column_sql, options
        execute change_column_sql
      end
    end
  end
end


config/initializers などに突っ込んで、migration で

change_column_collation :ranking_keywords, :name, nil

とやれば、表記揺れを吸収しないようになります。
第 3 引数に collate の設定を書けるようにしているので、表記揺れを吸収したいときは

change_column_collation :ranking_keywords, :name, 'utf8_unicode_ci'

のように書きます。