Help us understand the problem. What is going on with this article?

ActiveRecordでカラム毎にcharsetとcollationを指定する

More than 5 years have passed since last update.

MySQLではカラム毎にcharsetとcollationを指定できるので、こういうMigrationファイルがあったときに

db/migrate/20131120120000_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :email, charset: 'ascii', collation: 'ascii_bin', null: false
      t.string :password_digest, charset: 'ascii', collation: 'ascii_bin'
      t.timestamps
    end

    add_index :users, :email, name: "idx_email", unique: true
  end
end

こういうテーブルをCREATEしてほしい。

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
  `password_digest` varchar(255) CHARACTER SET ascii COLLATE ascii_bin DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC

ちょっと長いけど以下のコードをてきとうにRailsで読み込まれるところにコピペしてもらうといい感じに動くのではないかと思います。

config/initializers/activerecord.rb
ActiveSupport.on_load :active_record do

require 'active_record/connection_adapters/abstract_mysql_adapter'

module ActiveRecord::ConnectionAdapters
  class AbstractMysqlAdapter
    class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
      attr_accessor :charset, :collation
    end

    class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
      def new_column_definition(name, type, options) # :nodoc:
        column = super
        column.charset = options[:charset]
        column.collation = options[:collation]
        column
      end

      private

      def create_column_definition(name, type)
        ColumnDefinition.new(name, type)
      end
    end

    class SchemaCreation < AbstractAdapter::SchemaCreation
      def column_options(o)
        column_options = super
        column_options[:charset] = o.charset
        column_options[:collation] = o.collation
        column_options
      end

      def add_column_options!(sql, options)
        if options[:charset]
          sql << " CHARACTER SET #{options[:charset]}"
        end
        if options[:collation]
          sql << " COLLATE #{options[:collation]}"
        end
        super
      end
    end

    def prepare_column_options(column, types)
      spec = super
      spec[:collation] = column.collation.inspect if column.collation && column.collation != collation
      spec
    end

    def migration_keys
      super + [:collation]
    end

    private

    def create_table_definition(name, temporary = false, options = nil, as = nil)
      TableDefinition.new(native_database_types, name, temporary, options, as)
    end
  end
end

end

Rails 4.0.0以降で動きます。

【追記】上記のパッチはactiverecord-mysql-awesomeにてリリースしているのでこちらをお使い頂くのがよいかと思います。

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