RailsでActiveRecordモデルとそのテーブルの名前を変更するマイグレーションをどのように記述しますか?


408

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


11
検索エンジンの一致を改善するために、この質問に「ActiveRecord」を追加することを提案しました。「ActiveRecord rename table」を使ってこれを探していました。
Landon Kuhn

6
マイグレーションを使用している場合、この問題は見かけよりも複雑です。選択したソリューションでは、テーブル名を変更した後、モデルやコントローラーなどの名前を手動で変更するように指示されています。これを行うと、古い名前でモデルを参照する古い移行はすべて失敗します。したがって、誰かがリポジトリを複製して実行しようとするとrake db:migrate、失敗します。マイグレーションでこれらの名前に戻って変更することもできますが、これは面倒になります。名前を変更するよりも、まったく新しいモデルを作成した方がよい場合があります。
アンドリュー、

4
@andrewhannigan:誰かがあなたのレポを複製して実行しただけなら、あなたのポイントは意味がないrake db:schema:loadでしょうか?
istrasci 2013年

3
@istrasci:絶対に。実際、rake db:migrateアンドリューが指摘した懸念があるため、データベースを最初からセットアップして実行することは積極的にお勧めできません。
ジュゼッペ

回答:


584

次に例を示します。

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::CommandRecorderrename_tableの移行を元に戻す方法を知っているので、これを行うことができます。

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

(引き続き、ファイルの名前を手動で変更する必要があります。)


6
@mathee:はい、手動で変更するか、Rubyリファクタリングを実行してバージョン管理システムにコミットできるIDEを使用する必要があります。
pupeno 2010

13
git grepはあなたの友達です。現在、アクティビティの名前をHabitに変更していgit grep -i activitます。非常にわかりやすいです。
Felix Rabe

1
コントローラーの内容も変更する必要がありますよね?
alemur

5
そして、あなたのroutes.rbを忘れないでください!
ダンハーマン

26
また、ヘッドアップとして、rename_table呼び出しで複数バージョンのテーブル名を使用したいとします。
Han

66

Rails 4では、私がしなければならなかったすべては、defの変更でした

def change
  rename_table :old_table_name, :new_table_name
end

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

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


47

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

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

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

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

26

インデックスを置き換える必要もあります:

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を確認してください。おそらくそれらも編集する必要があります。

そして最後に、リグレッションテストスイートなしでこれを行うのは大変です。


11
Rails 4.0.0.beta1の移行については、インデックスを手動で更新する必要はありません。ARはそれ自体を更新します。
freemanoid

1

次のコマンドを実行できます:rails g migration rename_ {old_table_name} to {new_table_name}

ファイルを編集し、このコードをメソッド変更に追加した後

rename_table:{old_table_name}、:{new_table_name}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.