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.
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
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 })
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.
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
Rails 4:
def change
change_column_null(:users, :admin, false )
end
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
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