Adding :default => true to boolean in existing Rai

2019-01-12 23:11发布

问题:

I've seen a few questions (namely this one) here on SO about adding a default boolean value to an existing column. So I tried the change_column suggestion but I mustn't be doing it right.

I tried:

$ change_column :profiles, :show_attribute, :boolean, :default => true

Which returns -bash: change_column: command not found

I then ran:

$ rails g change_column :profiles, :show_attribute, :boolean, :default => true

...and

$ rails change_column :profiles, :show_attribute, :boolean, :default => true

Then ran rake db:migrate, but the value for :show_attribute remained nil. In the question I referenced above it says in PostgreSQL you need to update it manually. Since I'm using PostgreSQL I added the following in my create_profiles migration:

t.boolean :show_attribute, :default => true

Can someone tell me what I'm doing wrong here?

回答1:

change_column is a method of ActiveRecord::Migration, so you can't call it like that in the console.

If you want to add a default value for this column, create a new migration:

rails g migration add_default_value_to_show_attribute

Then in the migration created:

def up
  change_column :profiles, :show_attribute, :boolean, default: true
end

def down
  change_column :profiles, :show_attribute, :boolean, default: nil
end

Then run rake db:migrate.

It won't change anything to the already created records. To do that you would have to create a rake task or just go in the rails console and update all the records.

When you added t.boolean :show_attribute, :default => true to the create_profiles migration, it's normal if it didn't do anything. Only migrations that have not already been ran are executed. If you started with a fresh database, then it would set the default to true.



回答2:

As a variation on the accepted answer you could also use the change_column_default method in your migrations:

def up
  change_column_default :profiles, :show_attribute, true
end

def down
  change_column_default :profiles, :show_attribute, nil
end

Rails API-docs



回答3:

I'm not sure when this was written, but currently to add or remove a default from a column in a migration, you can use the following:

change_column_null :products, :name, false

Rails 5:

change_column_default :products, :approved, from: true, to: false

http://edgeguides.rubyonrails.org/active_record_migrations.html#changing-columns

Rails 4.2:

change_column_default :products, :approved, false

http://guides.rubyonrails.org/v4.2/active_record_migrations.html#changing-columns

Which is a neat way of avoiding looking through your migrations or schema for the column specifications.



回答4:

change_column :things, :price_1, :integer, default: 123, null: false

Seems to be best way to add a default to an existing column that doesn't have null: false already.

Otherwise:

change_column :things, :price_1, :integer, default: 123

Some research I did on this:

https://gist.github.com/Dorian/417b9a0e1a4e09a558c39345d50c8c3b



回答5:

If you just made a migration, you can rollback and then make your migration again.

To rollback you can do as many steps as you want:

rake db:rollback STEP=1

Then, you can just make the migration again:

def change
  add_column :profiles, :show_attribute, :boolean, default: true
end

Don't forget to rake db:migrate and if you are using heroku heroku run rake db:migrate



回答6:

Also, as per the doc:

default cannot be specified via command line

https://guides.rubyonrails.org/active_record_migrations.html

So there is no ready-made rails generator. As specified by above answers, you have to fill manually your migration file with the change_column_default method.

You could create your own generator: https://guides.rubyonrails.org/generators.html