UPDATE: added support for remove_index :users, :name=>:index_name
Mysql::Error: Duplicate key name ‘index_xxx’: CREATE INDEX `index_xxx` ON `users` (`xxx`) ?
Mysql::Error: Can’t DROP ‘index_xxx’; check that column/key exists: DROP INDEX `index_xxx` ON users ?
nevermore!
class TestAddRemoveIndex < ActiveRecord::Migration def self.up add_index :users, [:a, :b], :quiet=>true add_index :users, [:a, :b], :quiet=>true end def self.down remove_index :users, [:a, :b], :quiet=>true remove_index :users, [:a, :b], :quiet=>true end end
These patches allow you to add indices in a migration that will only be created if they do not already exist, or to remove indices only if they already exist through :quiet=>true.
module ActiveRecord::ConnectionAdapters::SchemaStatements def add_index_with_quiet(table_name, column_names, options = {}) quiet = options.delete(:quiet) add_index_without_quiet table_name, column_names, options rescue raise unless quiet and $!.message =~ /^Mysql::Error: Duplicate key name/i puts "Failed to create index #{table_name} #{column_names.inspect} #{options.inspect}" end alias_method_chain :add_index, :quiet def remove_index_with_quiet(table_name, *args) options = args.extract_options! quiet = options.delete(:quiet) if args.empty? remove_index_without_quiet table_name, options else remove_index_without_quiet table_name, *args end rescue rescue raise unless quiet and $!.message =~ /^Mysql::Error: Can't DROP/i puts "Failed to drop index #{table_name} #{(args[1]||options[:name]).inspect}" end alias_method_chain :remove_index, :quiet end
Hey,
because I needed the same thing for some other projects I have some code which more or less does the same, but on a different level. I can provide you with some Sqlite3 code, if you want to integrate that.
Besides I would consider putting these changes into a module and use super instead of the method_chain methods (viz http://yehudakatz.com/2009/03/06/alias_method_chain-in-models/ )