¿Cómo cambiar una columna nullable a not nullable en una migración de Rails?


Creé una columna de fecha en una migración anterior y la establecí como nullable. Ahora quiero cambiarlo para que no sea anulable. ¿Cómo hago esto asumiendo que hay filas nulas en esa base de datos? Estoy de acuerdo con ajustar esas columnas a la hora.ahora si actualmente son null.

Author: Kevin Pang, 2011-05-11

7 answers

Si lo haces en una migración, probablemente podrías hacerlo así:

# Make sure no null value exist
MyModel.where(date_column: nil).update_all(date_column: Time.now)

# Change the column to not allow null
change_column :my_models, :date_column, :datetime, null: false
 177
Author: DanneManne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-17 12:42:41

En Rails 4, esta es una mejor solución (SECO):

change_column_null :my_models, :date_column, false

Para asegurarse de que no existen registros con null valores en esa columna:

MyModel.update_all({ date_column: Time.now }, { date_column: nil })
 121
Author: mrbrdo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-18 23:17:50

Rails 4 (otras respuestas de Rails 4 tienen problemas):

def change
  change_column_null(:users, :admin, false, <put a default value here> )
  # change_column(:users, :admin, :string, :default => "")
end

Cambiar una columna con valores NULL para no permitir NULL causará problemas. Este es exactamente el tipo de código que funcionará bien en su configuración de desarrollo y luego se bloqueará cuando intente implementarlo en su producción EN VIVO . Primero debe cambiar los valores NULL a algo válido y luego no permitir NULLs. El 4to valor en change_column_null hace exactamente eso. Ver documentación para más información detalles.

Además, generalmente prefiero establecer un valor predeterminado para el campo, por lo que no tendré que especificar el valor del campo cada vez que cree un nuevo objeto. Incluí el código comentado para hacer eso también.

 58
Author: Rick Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-02 20:25:58

Cree una migración que tenga una instrucción change_column con un valor :default =>.

change_column :my_table, :my_column, :integer, :default => 0, :null => false

Ver: change_column

Dependiendo del motor de base de datos es posible que necesite usar change_column_null

 27
Author: jessecurry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-08 20:20:10

Rails 4:

def change
  change_column_null(:users, :admin, false )
end
 11
Author: piratebroadcast,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-20 16:36:11

In Rails 4.02+according to the docs there is no method like update_all with 2 arguments. En su lugar se puede utilizar este código:

# Make sure no null value exist
MyModel.where(date_column: nil).update_all(date_column: Time.now)

# Change the column to not allow null
change_column :my_models, :date_column, :datetime, null: false
 3
Author: jmarceli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-30 09:55:49

No puedes usar add_timestamps y null: false si tienes registros existentes, así que aquí está la solución:

def change
  add_timestamps(:buttons, null: true)

  Button.find_each { |b| b.update(created_at: Time.zone.now, updated_at: Time.zone.now) }

  change_column_null(:buttons, :created_at, false)
  change_column_null(:buttons, :updated_at, false)
end
 1
Author: Nicolas Maloeuvre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-18 23:17:33