简体   繁体   中英

Rails migration add default not null properties to existing boolean field

I have a rails model that has a non-defaulted boolean field that is nullable and am trying to set a default. I found a blog post about avoiding a 3-stat boolean issue, so am trying to cater for this. This is the migration I have:

def change
  change_column :table, is_foo, :boolean, null: false, default: false
end

Running the migration fails because of existing null values in the database. What is the correct way to update existing entries to allow the schema change? Or should the not null control be added to the model:

validates :is_foo, presence: true

Not sure if adding this to the migration is the "right" way:

 Table.update_all(:is_foo => false)

Similarly, this field was added by a migration without extra not null / default parameters. Would the migration to add column also require this, or would the default set the value? Here's the migration I ran:

add_column :table, is_foo, :boolean

If I had added ,null: false, default: false on the add_column, would all the values have been set correctly?

You could do it this way:

class UpdateFoo < ActiveRecord::Migration
  def change
    reversible do |direction|
      direction.up {
        Table.where(is_foo: nil).update_all(is_foo: false)
      }
    end
    change_column :table, :is_foo, :boolean, null: false, default: false
  end
end

When migrating up it will ensure first that all nulls are converted to false and then change the column to add your restrictions.

And yes, you could have avoided this if the first migration contained the restrictions.

I think you are also right adding the model validation.

You can actually combine the change_column_null and change_column_default methods to accomplish this in a migration.

  1. The change_column_null method lets you add a NOT NUL L constraint, with the last argument specifying what to replace any existing NULL values with.

  2. The change_column_default then sets the default for any new records.

class UpdateTable < ActiveRecord::Migration
  def change
    change_column_null :table, :is_foo, false, false
    change_column_default :table, :is_foo, false
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM