Я использую Rails 3.2.6 и Mysql 6.0.9 (но у меня точно такая же ошибка в MySQL 5.2.25)
Когда я создаю новую базу данных (rake db:create
), а затем, когда пытаюсь загрузить схему (rake schema:load
), я получаю эту ошибку:
Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE UNIQUE INDEX `unique_schema_migrations` ON `schema_migrations` (`version`)
После нескольких часов исследований я нашел следующие решения:
1. Измените переменную MySQL innodb_large_prefix на true (или ON).
Это не сработало. Я пробовал это на своем Linux-сервере, на своем Mac и даже на Windows — это просто не работает.
2. Monkeypatch ActiveRecord::SchemaMigration.create_table
Мне не нужно, чтобы столбец version
имел длину 255 (когда это UTF-8, тогда он занимает 4 * 255 = 1020 байт и превышает ограничение MySQL в 767 байт для ключей). Мне также не нужно, чтобы это было UTF-8, но все остальные таблицы в БД имеют UTF-8, и я установил utf8_czech_ci в качестве сопоставления по умолчанию.
Метод, который фактически создает таблицу schema_migrations, выглядит так:
def self.create_table
unless connection.table_exists?(table_name)
connection.create_table(table_name, :id => false) do |t|
t.column :version, :string, :null => false
end
connection.add_index table_name, :version, :unique => true, :name => index_name
end
end
Вы можете прочитать весь файл на Github rails/rails.
Поэтому я попытался добавить :limit => 100
к оператору t.column
, но и это решение мне не удалось. Проблема в том, что я не могу загрузить этот патч, когда оригинал уже на месте. Другими словами, мой патч загружается до ActiveRecord::SchemaMigration, поэтому он перезаписывается.
Когда я помещаю это в config/initializers/patches/schema_migration.rb
:
require 'active_record/scoping/default'
require 'active_record/scoping/named'
require 'active_record/base'
module ActiveRecord
class SchemaMigration < ActiveRecord::Base
def self.create_table
unless connection.table_exists?(table_name)
connection.create_table(table_name, :id => false) do |t|
t.column :version, :string, :null => false, :limit => 100
end
connection.add_index table_name, :version, :unique => true, :name => index_name
end
end
end
end
Он успешно загружен, но перезаписывается при загрузке исходного ActiveRecord::SchemaMigration.
Я пытался испортить ActiveSupport.on_load(:active_record), но это тоже не работает.
Есть ли способ загрузить этот файл после установки оригинального ActiveRecord::SchemaMigration и заставить этот патч работать?
У Вас есть какие-то предложения? Я могу прояснить любую часть этого вопроса, если это не имеет для вас смысла. Просто спроси у меня. Я застрял с этим слишком долго.
schema_migrations
(вместе с разумным размером столбца) вручную, прежде чем вообще делать какие-либо действия с Rails? - person mu is too short   schedule 25.07.2012rake db:test:clone
? Кроме того, это усложнит настройку на рабочих серверах/компьютерах разработчиков, потому что мне придется запустить некоторый скрипт для предварительной инициализации базы данных и создания этой таблицы. - person Lukáš Voda   schedule 25.07.2012