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/ )