インデックスの文字数制限もSchemaDumpできるようにする

MySQLのあるテーブルにINDEXをつけていたのだけれど、フィールドの型がTEXTだったので、「最初の500文字まで」という制限をかけていた。(MySQLではINDEXをつけられる文字数に制限がある)ところがこの文字数制限、RailsのSchemaDumperではダンプできない。
で、Schema中にはSQLを直接書いていたのだけれど、それだとテストができないのだ。
rakeでテストを走らせると、「開発用DBからRuby形式でテーブル形式をダンプ→それをテスト用データベースに適用」する。のだけれど、上述の制限がうまく動いていない。SQL形式でダンプするやり方があるだろうと探したのだけれど、見つける前にRuby形式に適当に手を入れた方が早そうだと思った。ので、作った。

# インデックスの制限もDumpできるようにする
module ActiveRecord
  module ConnectionAdapters
    class MysqlAdapter < AbstractAdapter
      def indexes(table_name, name = nil)#:nodoc:
        indexes = []
        current_index = nil
        execute("SHOW KEYS FROM #{table_name}", name).each do |row|
          if current_index != row[2]
            next if row[2] == "PRIMARY" # skip the primary key
            current_index = row[2]
            indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", [])
          end
          cname = [row[4]]
          cname <<  "(#{row[7]})" if row[7]
          cname = cname[0] if cname.size == 1
          indexes.last.columns << cname
        end
        indexes
      end
    end
  end
  module ConnectionAdapters # :nodoc:
    module SchemaStatements
      def add_index(table_name, column_name, options = {})
        column_names = Array(column_name)
        index_name   = index_name(table_name, :column => column_names.first)

        if Hash === options # legacy support, since this param was a string
          index_type = options[:unique] ? "UNIQUE" : ""
          index_name = options[:name] || index_name
        else
          index_type = options
        end
        quoted_column_names = column_names.map { |e|
          if e.is_a? Array
            n = e.shift
            quote_column_name(n) + e.join(" ")
          else
            quote_column_name(e)
          end
        }.join(", ")
        execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{table_name} (#{quoted_column_names})"
      end
    end
  end
end
  • これを lib/schema_dumper_putch.rb として保存
  • Rakefile
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'

require 'lib/schema_dumper_patch.rb' # これを追加

require 'tasks/rails'

すると、何とか上手くテストが起動できるようになった。よかった。
形式があまりにその場しのぎなので、応用性はないかもしれないけど。