私はDeviseを既存のRailsアプリに既に追加しています。Usersテーブルは既に定義されています。deviseジェネレーターは次の移行を推進しました。
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
...しかしサイコロはありません。私はRails 3.1.0、Ruby 1.9.2、rake 0.9.2.2、Postgresで実行しています。
私を失望させているコマンドは次のとおりです。
bundle exec rake db:rollback STEP=1
移行を正常に適用した後。何かアドバイス?
データベースの種類によっては、self.down
メソッドでインデックスを削除することを心配する必要はありません。列を削除するとインデックスがデータベースから自動的に削除されるためです。
self.down
メソッドで次の構文を使用することもできます。
def self.down
remove_column :users, :email
remove_column :users, :encrypted_password
remove_column :users, :reset_password_token
end
レコードの場合、名前でインデックスを削除する方法は
remove_index(:table_name, :name => 'index_name')
あなたの場合
remove_index(:users, :name => 'index_users_on_email')
また、列を指定するインデックスを削除することもできます。これは、私の観点からは、名前を書くよりもエラーが少ないです。
remove_index :actions, :column => [:user_id, :action_name]
@iWasRobbedの答えを詳しく説明したいと思います。単一の列のみにインデックスがある場合、remove_index
は(単なる仮定として!)DBがそのインデックスによって使用されるリソースをクリーンアップするのに十分スマートである必要があるため、意味がありません。ただし、複数の列のインデックスがある場合、列を削除するとインデックスがまだ存在する列に減少します。これは実行するのが賢明なことですが、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
この欠陥を修正し、rake db:rollback
これの私の完全な実行です(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) ==================
テーブルおよび/またはそのインデックスを変更するには、移行の#change_table
アクション内で #change
を使用します。次に、次のように可逆インデックスの削除を作成できます。
def change
change_table :users do |t|
t.index :email, :unique => true
t.index :reset_password_token, :unique => true
end
end
もちろん、リバーシブルアクションを使用してインデックス付きのテーブルを削除する必要がある場合は、SchemaStatements
の #drop_table
メソッドをTable
の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
メソッドとともに #remove_index
Table
の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
すべてのメソッドは、2.1.0
またはそれ以前のRails
バージョンで使用できます。