290

How do I add a default value to a column that already exists through a migration?

All the documentation I can find shows you how to do it if the column doesn't already exist but in this case it does.

Jon
  • 3,625
  • 4
  • 24
  • 21

7 Answers7

371

Here's how you should do it:

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

But some databases, like PostgreSQL, will not update the field for rows previously created, so make sure you update the field manaully on the migration too.

Maurício Linhares
  • 37,947
  • 14
  • 116
  • 153
198
change_column_default :employees, :foreign, false
Soviut
  • 79,529
  • 41
  • 166
  • 227
Gazza
  • 2,931
  • 1
  • 17
  • 20
  • 1
    @DenisLins I agreed with you, so I did some research to figure out why it might not be, and it turns out there's a possibility that a particular database adapter doesn't support it, as it's implemented at that level. The accepted answer is still the safest bet until it's implemented in the abstract model. http://apidock.com/rails/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter/SchemaStatements/change_column_default – natchiketa Jul 21 '15 at 14:54
  • 7
    Besides that, you need to specify a `from:` and `to:` if you want it to be reversible :) – radubogdan Mar 27 '17 at 11:34
  • 7
    **Using `from` and `to` was added in Rails 5+ in this commit: https://github.com/rails/rails/pull/20018/files** – Joshua Pinter Dec 29 '18 at 19:03
129

For Rails 4+, use change_column_default

def change
  change_column_default :table, :column, value
end
davegson
  • 7,419
  • 4
  • 47
  • 67
csi
  • 8,059
  • 8
  • 55
  • 78
  • 1
    This is great especially if you have a migration that is adding a column and setting defaults for existing records. For example: `def change` ` add_column :foos, :name, default: "something for existing values"` ` change_column_default :foos, :name, default: ""` `end` – user1491929 Jan 04 '16 at 16:14
  • 5
    This migration have a strange behaviour. In yours example it's irreversible. http://edgeguides.rubyonrails.org/active_record_migrations.html recommend to use it this way: `change_column_default :products, :approved, from: true, to: false` — but it doesn't works too. – Ilya Krigouzov May 13 '16 at 17:06
  • can't rollback using that? – aldrien.h Feb 27 '18 at 11:39
  • Usually so yes, for almost any "Change" clause, since all previous states are usually explicit, such as the presence of a column, it's type, etc. The change can be rolled back as it's shown there if and only if there was a valid explicit default previously. Since it's common that defaults are undefined, you might have an issue there. – Elindor Dec 16 '19 at 21:30
53

Using def change means you should write migrations that are reversible. And change_column is not reversible. You can go up but you cannot go down, since change_column is irreversible.

Instead, though it may be a couple extra lines, you should use def up and def down

So if you have a column with no default value, then you should do this to add a default value.

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

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

Or if you want to change the default value for an existing column.

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

def down
  change_column :users, :admin, :boolean, default: true
end
bfcoder
  • 2,852
  • 1
  • 25
  • 35
44

**Rails 4.X +**

As of Rails 4 you can't generate a migration to add a column to a table with a default value, The following steps add a new column to an existing table with default value true or false.

1. Run the migration from command line to add the new column

$ rails generate migration add_columnname_to_tablename columnname:boolean

The above command will add a new column in your table.

2. Set the new column value to TRUE/FALSE by editing the new migration file created.

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

**3. To make the changes into your application database table, run the following command in terminal**

$ rake db:migrate
James Bush
  • 83
  • 1
  • 8
Praveen George
  • 7,399
  • 4
  • 20
  • 45
  • How is this any different to rails 3+ or 2+? – Ruby Racer Feb 06 '16 at 16:05
  • 3
    Does anyone know if this has been incorporated into Rails 5? – sambecker Sep 01 '16 at 17:23
  • @sambecker I know I might be a little late replying to your comment, but it's working for me on Rails 6.0.3.1 – Mathyou Aug 16 '20 at 15:16
  • @Mathyou good to know. In Rails 6 can a new table have columns with default values? Or is still a separate migration? – sambecker Aug 17 '20 at 16:20
  • @sambecker you can definitely set default values in the new table migration. One of my columns in such a migration looks like: `t.boolean :is_active, :null => false, :default => false` – Mathyou Jan 14 '21 at 01:13
9

Execute:

rails generate migration add_column_to_table column:boolean

It will generate this migration:

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

Set the default value adding :default => 1

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

Run:

rake db:migrate

axeltaglia
  • 2,397
  • 1
  • 11
  • 4
  • 2
    Now the default value of 1 is not exactly a boolean ;) Also, this exampe *adds* a new column, instead of changing the existing column, which is what the OP wanted to achieve – radiospiel Sep 04 '13 at 11:18
  • @radiospiel Actually, 1 is a boolean too :) – kinduff Nov 12 '13 at 01:32
  • You will also need to create a record in the foreign key table with an ID of 1 for this to work, to avoid the `Key is not present in table error`. – Promise Preston Mar 21 '20 at 12:40
-55

This is what you can do:

class Profile < ActiveRecord::Base
  before_save :set_default_val

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

EDIT: ...but apparently this is a Rookie mistake!

rmcsharry
  • 4,357
  • 4
  • 50
  • 87
rookieRailer
  • 2,277
  • 2
  • 27
  • 46