Rails 3.1.0迁移中remove_index的正确语法是什么?

dou*_*lea 64 ruby-on-rails rails-migrations ruby-on-rails-3.1

我正在将Devise添加到现有的Rails应用程序中,并且已经定义了Users表.设计生成器推出了以下迁移:

class AddDeviseToUsers < ActiveRecord::Migration
  def self.up
    change_table(:users) do |t|

     ## Database authenticatable
     t.string :email,              :null => false, :default => ""
     t.string :encrypted_password, :null => false, :default => ""

     ## Recoverable
     t.string   :reset_password_token
     t.datetime :reset_password_sent_at

     ## Rememberable
     t.datetime :remember_created_at

     ## Trackable
     t.integer  :sign_in_count, :default => 0

     blah blah blah....

   end

   add_index :users, :email,                :unique => true
   add_index :users, :reset_password_token, :unique => true
 end
Run Code Online (Sandbox Code Playgroud)

没有生成向下迁移,我有一点时间删除这些索引.我在文档中看到了不同的建议表示法,并在网上提出了不同的建议,但似乎没有一个对我有用.例如...

def self.down
  change_table(:users) do |t|
    t.remove  :email
    t.remove  :encrypted_password

    t.remove  :reset_password_token

    blah blah blah...
  end

  remove_index :users, :email
  remove_index :users, :reset_password_token
end
Run Code Online (Sandbox Code Playgroud)

结果是...

An error has occurred, this and all later migrations canceled:

Index name 'index_users_on_email' on table 'users' does not exist
Run Code Online (Sandbox Code Playgroud)

这很奇怪,因为如果我检查数据库,果然,'index_users_on_email'就在那里......

我尝试过其他变种,包括

remove_index :users, :column => :email

remove_index :users, 'email'
Run Code Online (Sandbox Code Playgroud)

要么:

change_table(:users) do |t|
  t.remove_index :email
end
Run Code Online (Sandbox Code Playgroud)

......但没有骰子.我正在使用Postgres运行Rails 3.1.0,Ruby 1.9.2,rake 0.9.2.2.

令我失望的命令是:

bundle exec rake db:rollback STEP=1
Run Code Online (Sandbox Code Playgroud)

成功应用迁移后.有什么建议?

Dty*_*Dty 155

对于记录,按名称删除索引的方法是

remove_index(:table_name, :name => 'index_name')
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下

remove_index(:users, :name => 'index_users_on_email')
Run Code Online (Sandbox Code Playgroud)

  • 对于具有较新语法的copy-paster:`remove_index:users,name:'index_users_on_email'` (6认同)

Mar*_*ues 57

您还可以删除指定列的索引,从我的角度来看,它比写入名称更不容易出错

remove_index :actions, :column => [:user_id, :action_name]
Run Code Online (Sandbox Code Playgroud)

  • 对于这个问题,这将是`remove_index:users,column :: email`. (8认同)

iwa*_*bed 43

根据数据库类型,您无需担心删除self.down方法中的索引,因为删除列时将自动从数据库中删除索引.

您还可以在self.down方法中使用此语法:

def self.down
   remove_column :users, :email
   remove_column :users, :encrypted_password
   remove_column :users, :reset_password_token
end
Run Code Online (Sandbox Code Playgroud)

  • 根据这个问题的答案,删除列时不会删除索引:http://stackoverflow.com/questions/7204476/will-removing-a-column-with-a-rails-migration-remove-indexes - 相关 - 与-的 (8认同)

dol*_*nko 5

我想扩展@ iWasRobbed的答案.如果你只有单列的索引,那么担心remove_index没有意义,因为(只是一个假设!)数据库应该足够聪明,以清理该索引使用的资源.但是如果您有多列索引删除列将减少索引到仍然存在的列,这是完全明智的事情,但显示您可能想要remove_index明确使用的地方.

仅仅是为了说明 - 下面的迁移具有这样的缺陷,即在上下应用之后它会留下唯一索引email(意味着该down部分没有正常工作)

class AddIndexes < ActiveRecord::Migration
  def up
    add_column :users, :action_name, :string
    add_index  :users, [:email, :action_name], unique: true
  end

  def down
    remove_column :users, :action_name
  end
end
Run Code Online (Sandbox Code Playgroud)

down块更改为

  def down
    remove_index :users, [:email, :action_name]
    remove_column :users, :action_name
  end
Run Code Online (Sandbox Code Playgroud)

将修复该缺陷并允许迁移正确地将DB返回到先前的状态 rake db:rollback