2012-01-27 17 views
59

我正在將Devise添加到現有的Rails應用程序中,並且已經定義了Users表。該設計發生器推出了以下遷移:Rails 3.1.0遷移中remove_index的正確語法是什麼?

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 

向下遷移不生成,我有一個時間刪除這些索引。我在文檔中看到了不同的建議符號,並在網上提出了不同的建議,但是他們中的任何一個似乎都不適合我。例如...

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 

結果...

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

Index name 'index_users_on_email' on table 'users' does not exist 

這是奇怪的,因爲如果我檢查數據庫,果然, 'index_users_on_email' 就在那裏......

我試過其他的變化,包括

remove_index :users, :column => :email 

remove_index :users, 'email' 

或:

change_table(:users) do |t| 
    t.remove_index :email 
end 

......但沒有骰子。我正在使用Postgres運行Rails 3.1.0,Ruby 1.9.2,rake 0.9.2.2。

多數民衆贊成讓我失望的命令是:

bundle exec rake db:rollback STEP=1 

後成功應用遷移起來。有什麼建議?

+0

還記得首先刪除索引,然後刪除列,您的代碼會做另一種方式,即使您使用正確的語法將失敗。 – 2015-05-11 12:05:26

回答

41

根據數據庫類型的不同,您不必擔心刪除self.down方法中的索引,因爲刪除列時索引將自動從數據庫中刪除。

您也可以使用您的self.down方法的語法如下:

def self.down 
    remove_column :users, :email 
    remove_column :users, :encrypted_password 
    remove_column :users, :reset_password_token 
end 
+8

基於這個問題的答案,當你刪除列時索引不會被刪除:http://stackoverflow.com/questions/7204476/will-removing-a-column-with-a-rails-migration-remove-索引與 – Solomon 2014-04-30 22:13:25

+0

^有關^取決於數據庫類型 – iwasrobbed 2016-04-24 02:07:21

+0

要進一步瞭解@iwasrobbed的迴應,請小心使用此方法。如果你有一個複合索引並且只刪除MySQL中的一列,它仍然會離開索引。它只會引用剩餘的列。下面的迴應是明確刪除索引的更安全的方法。 – gordysc 2017-08-24 13:43:59

148

爲了記錄在案,以消除名稱索引的方式是

remove_index(:table_name, :name => 'index_name') 

所以你的情況

remove_index(:users, :name => 'index_users_on_email') 
+6

對於使用更新語法的複製貼圖:'remove_index:users,name:'index_users_on_email'' – Chambeur 2016-10-13 07:51:50

54

你也可以刪除指定列的索引,從我的角度來看這個列表更少錯誤或俯身比寫名字

remove_index :actions, :column => [:user_id, :action_name] 
+8

對於這個問題,這將是'remove_index:users,column :::email'。 – Will 2013-12-15 19:47:41

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 

更改down

def down 
    remove_index :users, [:email, :action_name] 
    remove_column :users, :action_name 
    end 

將修復漏洞,並允許遷移至正確返回DB到以前的狀態rake db:rollback

0

要改變一個表格和/或其使用#change_table裏面#change遷移的行爲。然後,你可以創建可逆式索引中刪除如下:

def change 
    change_table :users do |t| 
     t.index :email, :unique => true 
     t.index :reset_password_token, :unique => true 
    end 
end 

當你不得不刪除表,其過程與可逆式行動的指標,您可以使用#drop_table方法SchemaStatementsTable類爲ConnectionAdapter#index方法:

def change 
    drop_table :users do |t| 
     t.index :email, :unique => true 
     t.index :reset_password_token, :unique => true 
    end 
end 

如果您在遷移過程中確實需要#up/down對。使用只是一個#change_table方法隨着Table類的#remove_index方法ConnectionAdapter

def up 
    change_table :users do |t| 
     t.index :email, :unique => true 
     t.index :reset_password_token, :unique => true 
    end 
end 

def down 
    change_table :users do |t| 
     t.remove_index :email, :unique => true 
     t.remove_index :reset_password_token, :unique => true 
    end 
end 

所有的方法Rails版本的2.1.0或更早的人都可用。

0

這裏是我的這個完整的運行(在Rails中5):

我已經TEAM_ID如錶廠商的索引。我不再需要這種關係。擺脫它。做了以下事情:

1)創建遷移。

$ rails generate migration RemoveTeam_idFromVendor team_id:integer 

2)運行遷移,給我這個錯誤。這是因爲供應商的表有行中的外鍵引用隊表

== 20170727202815 RemoveTeamIdFromVendor: migrating =========================== 
-- remove_column(:vendors, :team_id, :integer) 
rake aborted! 
StandardError: An error has occurred, this and all later migrations canceled: 

SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "vendors" 

3)的主鍵值來解決這個問題,並得到遷移正在運行的,我做了以下(注:我在開發中) :

$ rake db:drop 


Dropped database 'db/development.sqlite3' 
Dropped database 'db/test.sqlite3' 


$ rake db:create 
Created database 'db/development.sqlite3' 
Created database 'db/test.sqlite3' 

$ rake db:migrate 
~ 
~ 
~ 

== 20170727202815 RemoveTeamIdFromVendor: migrating =========================== 
-- remove_column(:vendors, :team_id, :integer) 
    -> 0.0185s 
== 20170727202815 RemoveTeamIdFromVendor: migrated (0.0185s) ==================