web-dev-qa-db-ja.com

RailsでActiveRecordモデルとそのテーブルの名前を変更する移行をどのように記述しますか?

私は名前付けがひどく、私のRailsアプリにはモデルのより良い名前のセットがあることに気付きます。
移行を使用してモデルとそれに対応するテーブルの名前を変更する方法はありますか?

392
Readonly

以下に例を示します。

class RenameOldTableToNewTable < ActiveRecord::Migration
  def self.up
    rename_table :old_table_name, :new_table_name
  end

  def self.down
    rename_table :new_table_name, :old_table_name
  end
end

モデル宣言ファイルの名前を手動で変更する必要がありました。

編集:

Rails 3.1&4では、ActiveRecord::Migration::CommandRecorderはrename_tableの移行を逆にする方法を知っているので、これを行うことができます。

class RenameOldTableToNewTable < ActiveRecord::Migration
  def change
    rename_table :old_table_name, :new_table_name
  end 
end

(まだ、手動でファイル名を変更する必要があります。)

565
Readonly

Rails 4では、defを変更するだけでした。

def change
  rename_table :old_table_name, :new_table_name
end

そして、私のすべてのインデックスは私のために世話をされました。古いインデックスを削除して新しいインデックスを追加することにより、手動でインデックスを更新する必要はありませんでした。

また、インデックスに関しても上下に変更を使用して機能します。

62
bfcoder

他の回答とコメントでは、テーブルの名前変更、ファイルの名前変更、コード全体のgrepについて説明しました。

さらにいくつかの警告を追加したいと思います。

今日私が直面した実世界の例を使用してみましょう。「商人」から「ビジネス」にモデルの名前を変更します。

  • 同じ移行で依存テーブルとモデルの名前を変更することを忘れないでください。 MerchantモデルとMerchantStatモデルをBusinessとBusinessStatに同時に変更しました。そうでなければ、検索と置換を実行するときに、あまりにも多くのピッキングと選択を行う必要がありました。
  • 外部キーを介してモデルに依存する他のモデルの場合、他のテーブルの外部キー列名は元のモデル名から派生します。そのため、これらの依存モデルでいくつかのrename_column呼び出しを行うこともできます。たとえば、さまざまな結合テーブル(has_and_belongs_to_many関係の場合)およびその他の依存テーブル(通常のhas_oneおよびhas_many関係の場合)で「merchant_id」列の名前を「business_id」に変更する必要がありました。そうでなければ、「business.id」を指す「business_stat.merchant_id」のような列になってしまいます。 列の名前変更の実行に関する適切な回答を次に示します。
  • Grepするときは、文字列の単数形、複数形、大文字、小文字、さらには大文字(コメント内で発生する可能性があります)を検索することを忘れないでください。
  • 最初に複数形を検索し、次に単数形を検索するのが最善です。そうすれば、私の商人::ビジネスの例のように不規則な複数形がある場合、すべての不規則な複数形を正しく取得できます。そうしないと、たとえば「ビジネス」(3秒)が中間状態になり、検索と置換がさらに増える可能性があります。
  • すべての発生を盲目的に置き換えないでください。モデル名が一般的なプログラミング用語、他のモデルの値、またはビューのテキストコンテンツと競合する場合、過度に熱心になる可能性があります。この例では、モデル名を「ビジネス」に変更したかったのですが、UIのコンテンツではそれらを「商人」として参照していました。また、CanCanのユーザーには「マーチャント」の役割がありました。マーチャントの役割とマーチャントモデルの混乱により、そもそもモデルの名前が変更されました。
45
armchairdj

また、インデックスを置き換える必要があります。

class RenameOldTableToNewTable< ActiveRecord:Migration
  def self.up
    remove_index :old_table_name, :column_name
    rename_table :old_table_name, :new_table_name
    add_index :new_table_name, :column_name
  end 

  def self.down
    remove_index :new_table_name, :column_name
    rename_table :new_table_name, :old_table_name
    add_index :old_table_name, :column_name
  end
end

ここで他の答えが説明するように、手動でファイルなどの名前を変更します。

参照: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

この移行を記述した後、ロールバックおよびロールフォワードできることを確認してください。何か問題が発生し、存在しなくなったものに影響を与えようとする移行に取り付かれると、注意が必要になります。データベース全体を破棄して、ロールバックできない場合は再度開始することをお勧めします。したがって、何かをバックアップする必要がある場合があることに注意してください。

また、has_またはbelongs_toなどによって定義された他のテーブルの関連する列名についてschema_dbを確認します。おそらくこれらも編集する必要があります。

そして最後に、回帰テストスイートなしでこれを行うのは簡単です。

23
Rimian