移行を通じて列にデフォルト値を追加する


276

移行によって既に存在する列にデフォルト値を追加するにはどうすればよいですか?

私が見つけることができるすべてのドキュメントは、列がまだ存在しない場合にそれを行う方法を示していますが、この場合はあります。

回答:


352

これを行う方法は次のとおりです。

change_column :users, :admin, :boolean, :default => false

ただし、PostgreSQLなどの一部のデータベースでは、以前に作成された行のフィールドが更新されないため、移行時にもフィールドを手動で更新してください。


14
可逆的な移行が必要な場合は、これをupブロックではなくchangeブロックに配置します。downブロックを空のままにすることができます。テーブルは元の状態には戻りませんが、移行をロールバックできます。
IAmNaN 2014年

1
これはデータをそのまま維持しますか?
Marco Prins、2015年

2
PostgreSQLでは、はい、他のデータベースで何が起こるかわかりません。
マウリシオ・リニャレス

1
「マイグレーション時にフィールドを手動で更新するようにしてください」とはどういう意味ですか?どうやってそれを行うのですか?
David Argyle Thacker

7
PostgreSQLで試してみたところ、以前に作成したフィールドが更新されました。
Aboozar Rajabi 2016年

190
change_column_default :employees, :foreign, false

1
@DenisLins私はあなたに同意したので、なぜそうでないのかを理解するためにいくつかの調査を行いましたが、特定のデータベースアダプターがそのレベルで実装されているため、それをサポートしていない可能性があることがわかりました。受け入れられた回答は、抽象モデルに実装されるまで、最も安全な方法です。 apidock.com/rails/ActiveRecord/ConnectionAdapters/...
natchiketa

5
そのほかには、次のように指定する必要がありますfrom:し、to:あなたはそれが可逆:)にしたい場合
radubogdan

5
を使用fromしてto、このコミットのRails 5以降で追加されました:github.com/rails/rails/pull/20018/files
Joshua Pinter

115

以下のためのRails 4+、使用change_column_default

def change
  change_column_default :table, :column, value
end

1
これは、列を追加し、既存のレコードのデフォルトを設定する移行がある場合に特に便利です。例: def change `add_column:foos、:name、default:" something for existing values "` `change_column_default:foos、:name、default:" "`end
user1491929

2
この移行には奇妙な動作があります。あなたの例ではそれは不可逆的です。edgeguides.rubyonrails.org/active_record_migrations.htmlは、次のように使用することをお勧めしますchange_column_default :products, :approved, from: true, to: false。ただし、機能しません。
Ilya Krigouzov

それを使用してロールバックできないのですか?
aldrien.h

通常は「はい」です。ほとんどすべての「変更」句について、列の存在、タイプなど、以前のすべての状態は通常明示的であるためです。変更があった場合にのみ、そこに表示されるように変更をロールバックできます。以前は有効な明示的なデフォルト。デフォルトは未定義であることが一般的であるため、そこで問題が発生する可能性があります。
Elindor

48

使用def changeするということは、リバーシブルなマイグレーションを書く必要があるということです。そしてchange_column、可逆的ではありません。は元に戻すことはできますが、元に戻すことはできませんchange_column

代わりに、2、3行余分になることがありますがdef updef down

したがって、デフォルト値のない列がある場合は、これを行ってデフォルト値を追加する必要があります。

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: nil
end

または、既存の列のデフォルト値を変更する場合。

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: true
end

37

** Rails 4.X + **

Rails 4以降では、デフォルト値でテーブルに列を追加するマイグレーションを生成することはできません 。次の手順では、デフォルト値がtrueまたはfalseである既存のテーブルに新しい列を追加します。

1.コマンドラインから移行を実行して、新しい列を追加します

$ rails generate migration add_columnname_to_tablename columnname:boolean

上記のコマンドは、テーブルに新しい列を追加します。

2.作成された新しい移行ファイルを編集して、新しい列の値をTRUE / FALSEに設定します。

class AddColumnnameToTablename < ActiveRecord::Migration
  def change
    add_column :table_name, :column_name, :boolean, default: false
  end
end

** 3。アプリケーションデータベーステーブルに変更を加えるには、ターミナルで次のコマンドを実行します**

$ rake db:migrate

これはRails 3+または2+とどう違うのですか?
Rubyレーサー、

2
これがRails 5に組み込まれているかどうか誰かが知っていますか?
サンベッカー、

9

実行:

rails generate migration add_column_to_table column:boolean

この移行が生成されます:

class AddColumnToTable < ActiveRecord::Migration
  def change
    add_column :table, :column, :boolean
  end
end

デフォルト値を追加します:default => 1

add_column:table、:column、:boolean、:default => 1

実行:

rake db:migrate


2
現在、デフォルト値の1はブール値ではありません;)また、この例で、既存の列を変更するのではなく、新しい列を追加します。これは、OPが達成したかったことです
radiospiel

@radiospiel実際、1もブール値です:)
kinduff '12

また、これを機能させるには、IDが1の外部キーテーブルにレコードを作成して、を回避する必要がありKey is not present in table errorます。
Proston Preston

-50

これはあなたができることです:

class Profile < ActiveRecord::Base
  before_save :set_default_val

  def set_default_val
    self.send_updates = 'val' unless self.send_updates
  end
end

編集:...しかし、これは新人の間違いです!


スキーマでデフォルトを設定するのではなく、before_save
rigelstpierre

6
なんてひどい提案
スヴェランディア

同意した、それは本当にひどいです
Houcheng

3
さて、データベースレベルではなく、モデルレベルで何かを行うことには多くの熱があります。-38は伝説のスコアです。
ヌレティン2018年

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