Ruby on Railsの移行でデータベース列の名前を変更するにはどうすればよいですか?


回答:


2309
rename_column :table, :old_column, :new_column

これを行うには、おそらく別のマイグレーションを作成する必要があります。(必要に応じて名前を変更しFixColumnNameてください。):

script/generate migration FixColumnName
# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb

次に、移行を編集して意志を実行します。

# db/migrate/xxxxxxxxxx_fix_column_name.rb
class FixColumnName < ActiveRecord::Migration
  def self.up
    rename_column :table_name, :old_column, :new_column
  end

  def self.down
    # rename back if you need or do something else or do nothing
  end
end

Rails 3.1の場合:

、一方でupdown方法はまだ適用され、Railsの3.1には、受信しますchange「データベースを移行し、移行が別々のダウンメソッドを記述することなく、ロールバックされたときに、それを逆にする方法を知っている」という方法を。

詳細については、「アクティブレコードの移行」を参照してください。

rails g migration FixColumnName

class FixColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

名前を変更する列がたくさんある場合、またはテーブル名を何度も繰り返す必要がある場合:

rename_column :table_name, :old_column1, :new_column1
rename_column :table_name, :old_column2, :new_column2
...

あなたはchange_table物事を少しきちんと保つために使うことができます:

class FixColumnNames < ActiveRecord::Migration
  def change
    change_table :table_name do |t|
      t.rename :old_column1, :new_column1
      t.rename :old_column2, :new_column2
      ...
    end
  end
end

次にdb:migrate、いつものように、またはあなたがあなたのビジネスについて行きます。


Rails 4の場合:

Migration列の名前を変更するためのを作成しているときに、Rails 4 は上記のセクションのchange代わりにupdown前述のようにメソッドを生成します。生成されるchangeメソッドは次のとおりです。

$ > rails g migration ChangeColumnName

次のような移行ファイルが作成されます。

class ChangeColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

24
self.downは常に self.up の反対である必要があるため、「必要な場合、または何か他のことを行う場合、または何もしない場合」は、実際にはお勧めできません。ただ行う:rename_column:table_name、:new_column、:old_column
Luke Griffiths

3
あなたがしたことを元に戻すことは通常の習慣ですが、「常に反対であるべき」self.upとは言えません。移行のコンテキストによって異なります。「反対」を置くだけでは、「正しい」ダウンマイグレーションではない可能性があります。self.down
nowk

23
Railsの3.1では、あなたは置き換えることができるdef self.updef self.downしてdef change、それがロールバックする方法を知っていますよ。
Turadg、2009

2
Turadg-*ほとんどの場合、ロールバックする方法がわかります。このchange方法は完全な証拠ではないので、複雑な移行に使用する方法updown方法が多いと思います。
JellyFishBoy 2014年

6
名前を変更するとインデックスが削除されますか?
Sung Cho、

68

私の意見では、この場合は、を使用してrake db:rollbackから、移行を編集して、もう一度実行することをお勧めしますrake db:migrate

ただし、失わないようにするデータが列にある場合は、を使用しますrename_column


34
「1つのチーム」であっても、異なる環境や複数のコンピューターなどでアプリの複数のインスタンスを実行している場合、編集された移行を管理することは大きな問題です。私は場合にのみ、移行を編集するだけで、それを作成し、それが間違っていた実現し、まだどこにも文字通りそれを実行していません。
Yetanotherjosh 2013

1
その後、サーバーを再起動する必要がありました。
Muhammad Hewedy

7
この手法は、変更がまだ本番ブランチにマージされておらず、その他の変更がデータの永続性に依存していない状況でのみ使用する必要があります。ほとんどすべての生産環境で、これは推奨される方法ではありません。
Collin Graves

4
このようなことは決してしないでください。
new2cpp 2017

4
私は自分のチームに次のように言いたいです:「移行は無料です」実際にリリースされた移行を編集するコストは高くなります。別のチームメンバーに気付く前に、コードが機能しない理由を数時間かけて調査しました戻って、すでに実行しているマイグレーションを編集していました。そのため、既存の移行を編集しないでください。新しいものを使用してスキーマを変更してください。...「移行は無料です!」(厳密には真実ではありませんが、要点です)
TerryS、2017

31

列にすでにデータが入力されており、運用環境にある場合は、段階的なアプローチをお勧めします。これにより、移行を待機している間の運用環境でのダウンタイムを回避できます。

最初に、新しい名前で列を追加し、古い列名の値を入力するdbマイグレーションを作成します。

class AddCorrectColumnNames < ActiveRecord::Migration
  def up
    add_column :table, :correct_name_column_one, :string
    add_column :table, :correct_name_column_two, :string

    puts 'Updating correctly named columns'
    execute "UPDATE table_name SET correct_name_column_one = old_name_column_one, correct_name_column_two = old_name_column_two"
    end
  end

  def down
    remove_column :table, :correct_name_column_one
    remove_column :table, :correct_name_column_two
  end
end

次に、その変更だけをコミットして、変更を本番環境にプッシュします。

git commit -m 'adding columns with correct name'

次に、コミットが本番環境にプッシュされたら、実行します。

Production $ bundle exec rake db:migrate

次に、古い列名を参照していたすべてのビュー/コントローラーを新しい列名に更新します。テストスイートを実行し、それらの変更のみをコミットします。(それがローカルで動作していることを確認し、最初にすべてのテストに合格した後!)

git commit -m 'using correct column name instead of old stinky bad column name'

それから私はそのコミットメントを本番にプッシュします。

この時点で、移行自体に関連するあらゆる種類のダウンタイムを心配することなく、元の列を削除できます。

class RemoveBadColumnNames < ActiveRecord::Migration
  def up
    remove_column :table, :old_name_column_one
    remove_column :table, :old_name_column_two
  end

  def down
    add_column :table, :old_name_column_one, :string
    add_column :table, :old_name_column_two, :string
  end
end

次に、この最新の移行を本番環境にプッシュbundle exec rake db:migrateして、バックグラウンドで実行します。

これはプロセスに少し関わっていることに気づきましたが、本番環境への移行で問題が発生するよりは、こちらの方がいいと思います。


2
私はこれの背後にある考え方が好きで、あなたの返答を+1しますが、そのデータ更新は、一度に1行ずつレールを通過するため、実行に非常に長い時間がかかります。正しい名前の列を更新するための生のSQLステートメントを使用すると、移行がはるかに速く実行されます。たとえば、最初のdb移行スクリプトでは、重複する列名を追加した後 execute "Update table_name set correct_name_column_one = old_name_column_one"
Gui Weinmann

1
@ mr.ruh.roh ^完全に同意します。そもそもそれを書いているはずです。単一の効率的なSQLステートメントを反映するように編集しました。健全性チェックをありがとう。
ポールペッテンギル2013

2
新しいテーブルに移動してから新しいテーブルを使用するようにコードを更新するまでの間に、エントリはどうなりますか?移行されていない可能性のあるデータを残しておくことはできませんか?
Stefan Dorunga 2014年

1
これは「安全な」答えですが、私はそれが不完全だと感じています。ここの多くの人々はこれをしないと言います-なぜですか?データの永続性。そしてそれは有効です。おそらく、目標を達成するための最も苦痛の少ない方法は、新しいフィールドを作成し、古い列からのデータをフィールドに入力し、コントローラーを調整することです。古い列を削除したい場合は、ビューを編集する必要があります。それらを維持するためのコストは、余分なdbスペースと、コントローラーでの重複した作業です。したがって、トレードオフは明確です。
ジェローム


18

以下のコマンドを実行して、移行ファイルを作成します。

rails g migration ChangeHasedPasswordToHashedPassword

次に、db/migrateフォルダーに生成されたファイルに、rename_column次のように書き込みます。

class ChangeOldCoulmnToNewColumn < ActiveRecord::Migration
  def change
     rename_column :table_name, :hased_password, :hashed_password
  end
end

14

APIから:

rename_column(table_name, column_name, new_column_name)

列の名前を変更しますが、タイプと内容は同じままです。


12

Ruby on Railsの一部のバージョンは、移行のアップ/ダウン方式をサポートしており、移行にアップ/ダウン方式がある場合:

def up
    rename_column :table_name, :column_old_name, :column_new_name
end

def down
    rename_column :table_name, :column_new_name, :column_old_name
end

change移行にメソッドがある場合、次のようになります。

def change
    rename_column :table_name, :column_old_name, :column_new_name
end

詳細については、Ruby on Rails-MigrationsまたはActive Record Migrationsを移動してください


11

コードが他のコードと共有されていない場合はrake db:rollback 、移行およびで列名を編集することをお勧めしますrake db:migrate。それでおしまい

そして、列の名前を変更するために別のマイグレーションを書くことができます

 def change
    rename_column :table_name, :old_name, :new_name
  end

それでおしまい。


rake db:rollback素晴らしい提案です。しかし、あなたが言ったように、移行がまだプッシュされていない場合に限ります。
danielricecodes

9

別のオプションとして、移行のアイデアに慣れていない場合は、名前変更を自動的に処理するActiveRecordの魅力的な宝石、Datamapperスタイルがあります。行うのは、モデルの列名を変更するだけです(そして、model.rbの下部にModel.auto_upgrade!を配置してください)とviola!データベースはその場で更新されます。

https://github.com/DAddYE/mini_record

注:競合を防ぐためにdb / schema.rbをnukeする必要があります

まだベータ段階であり、明らかに誰もが使えるわけではありませんが、それでも説得力のある選択肢です(現在、問題のない2つの重要な製品アプリで使用しています)。


8

列名を切り替える必要がある場合は、列名の重複エラーを回避するためにプレースホルダーを作成する必要があります。次に例を示します。

class SwitchColumns < ActiveRecord::Migration
  def change
    rename_column :column_name, :x, :holder
    rename_column :column_name, :y, :x
    rename_column :column_name, :holder, :y
  end
end

7

現在のデータが重要でない場合は、以下を使用して元の移行を停止できます。

rake db:migrate:down VERSION='YOUR MIGRATION FILE VERSION HERE'

引用符がない場合は、元の移行に変更を加えて、次の方法で再度移行を実行します。

rake db:migrate

6

単に新しいマイグレーションを作成し、ブロックでrename_column以下のように使用します。

rename_column :your_table_name, :hased_password, :hashed_password


5

手動で以下の方法を使用できます:

次のように手動で移行を編集できます。

  • 開いた app/db/migrate/xxxxxxxxx_migration_file.rb

  • アップデートhased_passwordhashed_password

  • 以下のコマンドを実行します

    $> rake db:migrate:down VERSION=xxxxxxxxx

次に、移行を削除します。

$> rake db:migrate:up VERSION=xxxxxxxxx

更新された変更で移行が追加されます。


データが失われる可能性があるため、安全ではありません-カラムがすでに稼働している場合。しかし、新しい列やテーブルに対して行うことができます。
Tejas Patel、2015

5

移行ファイルを生成します。

rails g migration FixName

#db / migrate / xxxxxxxxxx.rbを作成します

移行を編集して、必要に応じて行います。

class FixName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

5

実行rails g migration ChangesNameInUsers(または名前を付けたいもの)

(中間だけで生成された移行ファイルを開き、この方法では、この行を追加def changeしてend):

rename_column :table_name, :the_name_you_want_to_change, :the_new_name

ファイルを保存rake db:migrateし、コンソールで実行します

schema.dbデータベースで名前が実際に変更されたかどうかを確認するには、をチェックしてください。

お役に立てれば :)


5

キスしましょう。必要なのは、3つの簡単なステップだけです。以下はRails 5.2で動作します

1。移行を作成する

  • rails g migration RenameNameToFullNameInStudents

  • rails g RenameOldFieldToNewFieldInTableName-そうすれば、後でコードベースのメンテナに完全に明確になります。(テーブル名には複数を使用します)。

2.移行を編集する

# I prefer to explicitly write theアップandダウンmethods.

# ./db/migrate/20190114045137_rename_name_to_full_name_in_students.rb

class RenameNameToFullNameInStudents < ActiveRecord::Migration[5.2]
  def up
    # rename_column :table_name, :old_column, :new_column
    rename_column :students, :name, :full_name
  end

  def down
            # Note that the columns are reversed
    rename_column :students, :full_name, :name
  end
end

3.移行を実行する

rake db:migrate

そして、あなたはレースに出かけています!


4
$:  rails g migration RenameHashedPasswordColumn
invoke  active_record
      create    db/migrate/20160323054656_rename_hashed_password_column.rb

その移行ファイルを開き、以下のようにそのファイルを変更します(元のを入力してくださいtable_name

class  RenameHashedPasswordColumn < ActiveRecord::Migration
  def change
    rename_column :table_name, :hased_password, :hashed_password
  end
end

4
 def change
    rename_column :table_name, :old_column_name, :new_column_name
  end

3

Ruby on Rails移行を生成します

$:> rails g migration Fixcolumnname

移行ファイル(XXXXXfixcolumnname.rb)にコードを挿入します

class Fixcolumnname < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

2

Ruby on Railsコンソールを開き、次のように入力します。

ActiveRecord::Migration.rename_column :tablename, :old_column, :new_column

2

これには2つの方法があります。

  1. このタイプでは、ロールバック時に自動的に逆のコードが実行されます。

    def change
      rename_column :table_name, :old_column_name, :new_column_name
    end
  2. このタイプでは、upメソッドがrake db:migrate実行され、downメソッドが実行されrake db:rollbackます。

    def self.up
      rename_column :table_name, :old_column_name, :new_column_name
    end
    
    def self.down
      rename_column :table_name,:new_column_name,:old_column_name
    end

2

私はレール5.2を使用しており、デバイスユーザーの列の名前を変更しようとしています。

rename_columnビットは私のために働いたが、単数形:table_name投げたエラーを「ユーザーテーブルが見つかりません」。複数は私のために働きました。

rails g RenameAgentinUser

次に、マイグレーションファイルを次のように変更します。

rename_column :users, :agent?, :agent

どこ:agent?古い列名です。


0

更新 -create_tableに近いものはchange_tableで、既存のテーブルを変更するために使用されます。create_tableと同様の方法で使用されますが、ブロックに渡されたオブジェクトはより多くのトリックを知っています。例えば:

class ChangeBadColumnNames < ActiveRecord::Migration
  def change
    change_table :your_table_name do |t|
      t.rename :old_column_name, :new_column_name
    end
  end
end

この方法は、インデックスの削除/追加/インデックスの削除/列の追加など、他の変更方法を使用する場合により効率的です。たとえば、次のようにすることもできます。

# Rename
t.rename :old_column_name, :new_column_name
# Add column
t.string :new_column
# Remove column
t.remove :removing_column
# Index column
t.index :indexing_column
#...

0

コマンドを使用してマイグレーションを生成するだけです

rails g migration rename_hased_password

その後、移行を編集して、変更方法に次の行を追加します

rename_column :table, :hased_password, :hashed_password

これでうまくいくはずです。


0

Rails 5移行の変更

例えば:

rails gモデルStudent student_name:string age:integer

student_name列を名前として変更する場合

注:-rails db:migrateを実行しない場合

次の手順を実行できます

rails dモデルStudent student_name:string age:integer

これにより、生成された移行ファイルが削除されます。これで、列名を修正できます

rails g model学生名:string年齢:integer

移行した場合(rails db:migrate)、列名を変更する次のオプション

rails g migration RemoveStudentNameFromStudent student_name:string

rails g migration AddNameToStudent name:string


それはすべきではありません:( rails g migration RemoveStudentNameFromStudentS student_name:string学生は複数です)?
BKSpurgeon

また、これは危険です。列の名前は変更されませんが、完全に削除されてから再度追加されます。データはどうなりますか?これはユーザーが望むものではないかもしれません。
BKSpurgeon
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.