Railsの移行:存在を確認して続行しますか?


80

私は自分の移行でこの種のことをしていました:

add_column :statuses, :hold_reason, :string rescue puts "column already added"

しかし、これはSQLiteでは機能しますが、PostgreSQLでは機能しないことがわかりました。add_columnが爆発した場合、例外がキャッチされてもトランザクションは停止しているため、Migrationは追加の作業を実行できないようです。

列またはテーブルがすでに存在するかどうかを確認するためのDB以外の特定の方法はありますか?それができない場合、レスキューブロックを実際に機能させる方法はありますか?


条件付き移行は、ロールバック段階では順方向移行中にどのような条件があったかがわからないため、ロールバックの問題につながることに注意する必要があります
oklas 2020

ロールバックでオプション以外の部分のみを実行する
DanRosenstark20年

回答:


175

Rails 3.0以降では、を使用column_exists?して列の存在を確認できます。

unless column_exists? :statuses, :hold_reason
  add_column :statuses, :hold_reason, :string
end

table_exists?Rails2.1までさかのぼる関数もあります。


追加/作成する前に列/テーブルが存在するかどうかを確認することがベストプラクティスと見なされますか?(もちろん、それは手の問題に依存することを私は知っています)
Aldo'xoen 'Giambelluca 2014

4
changeメソッドで定義した場合、これはロールバックで機能しますか?
dardub 2015

1
ええ、ロールバックが問題になるでしょう...前の状態を記録していないので、列を削除する必要があるかどうかはわかりません。
songyy 2016

8

またはさらに短い

add_column :statuses, :hold_reason, :string unless column_exists? :statuses, :hold_reason

これは、回答ではなく、他の回答に対するコメントになります。ありがとう。
ダンローゼンスターク2013

4

以下のためのRails 2.Xは、次の列の存在を確認することができます。

columns("[table-name]").index {|col| col.name == "[column-name]"}

nilを返す場合、そのような列は存在しません。Fixnumが返される場合、その列は存在します。当然、{...}名前だけでなく列を識別したい場合は、次のように、より選択的なパラメータを間に配置できます。

{ |col| col.name == "foo" and col.sql_type == "tinyint(1)" and col.primary == nil }

(この回答は、Railsで条件付き移行を作成する方法に最初に投稿されましたか?


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