Comment changer une colonne nullable en non nullable dans une migration Rails?

J'ai créé une colonne de date dans une migration précédente et l'ai définie comme nullable. Maintenant, je veux le changer pour ne pas être nullable. Comment puis-je faire cela en supposant qu'il y ait des lignes null dans cette base de données? Je suis d'accord avec la mise en place de ces colonnes à L'heure.maintenant, s'ils sont actuellement nuls.

156
demandé sur Kevin Pang 2011-05-11 19:34:33

7 réponses

Si vous le faites dans une migration alors que vous pourriez probablement faire comme ceci:

# 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
répondu DanneManne 2018-03-17 12:42:41

Dans Rails 4, c'est une meilleure solution (sèche):

change_column_null :my_models, :date_column, false

Pour s'assurer qu'aucun enregistrement n'existe avec les valeurs null dans cette colonne:

MyModel.update_all({ date_column: Time.now }, { date_column: nil })
121
répondu mrbrdo 2017-04-18 23:17:50

Rails 4 (les autres réponses Rails 4 ont des problèmes):

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

Changer une colonne avec des valeurs NULL pour ne pas autoriser NULL causera des problèmes. C'est exactement le type de code qui fonctionnera correctement dans votre configuration de développement, puis se bloque lorsque vous essayez de le déployer sur votre production LIVE. Vous devez d'abord changer les valeurs NULL en quelque chose de valide et puis interdire les valeurs Null. La 4ème valeur dans change_column_null fait exactement cela. Voir documentation pour plus d' détail.

En outre, je préfère généralement définir une valeur par défaut pour le champ, donc je n'aurai pas besoin de spécifier la valeur du champ chaque fois que je crée un nouvel objet. J'ai inclus le code commenté pour le faire aussi.

58
répondu Rick Smith 2015-09-02 20:25:58

Créez une migration qui a une instruction change_column avec une valeur :default =>.

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

Voir: change_column

Selon le moteur de base de données, vous devrez utiliser les change_column_null

27
répondu jessecurry 2015-02-08 20:20:10

Rails 4:

def change
  change_column_null(:users, :admin, false )
end
11
répondu piratebroadcast 2014-05-20 16:36:11

Dans Rails 4.02+ selon la docs il n'y a pas de méthode comme update_all avec 2 arguments. Au lieu de cela on peut utiliser ce code:

# 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
répondu jmarceli 2015-01-30 09:55:49

Vous ne pouvez pas utiliser add_timestamps et null: false si vous avez des enregistrements existants, alors voici la solution:

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
répondu Nicolas Maloeuvre 2017-04-18 23:17:33