231 votes

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

J'ai créé une colonne de date dans une migration précédente et je l'ai configurée pour qu'elle puisse être nulle. Je veux maintenant la changer pour qu'elle ne soit pas annulable. Comment dois-je procéder en supposant qu'il y a des lignes nulles dans cette base de données ? Je suis d'accord pour définir ces colonnes sur Time.now si elles sont actuellement nulles.

232voto

DanneManne Points 13408

Si vous le faites dans le cadre d'une migration, vous pouvez probablement le 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

1 votes

Juste une remarque, parce que cela m'a fait détruire ma base de données de développement. Utilisez plutôt une syntaxe de hachage explicite, comme ceci : MyModel.update_all({:date_column => Time.now}, {:date_column => nil}) . La requête dans votre formulaire original a fait que tous mes modèles ont une valeur nulle dans le champ.

0 votes

Merci pour cette mise à jour. Je sais que ce n'était pas le cas lorsque j'ai écrit cette réponse mais je ne me souviens pas de la version de Ruby ou de RoR que j'utilisais à l'époque.

1 votes

Devez-vous utiliser la méthode 'up'/'down' dans cette migration, ou pouvez-vous utiliser la méthode de changement simple dans la migration ?

228voto

mrbrdo Points 1818

Dans Rails 4, c'est une meilleure solution (plus DRY) :

change_column_null :my_models, :date_column, false

Pour s'assurer qu'aucun enregistrement n'existe avec NULL dans cette colonne, vous pouvez passer un quatrième paramètre, qui est la valeur par défaut à utiliser pour les enregistrements avec NULL valeurs :

change_column_null :my_models, :date_column, false, Time.now

4 votes

Cela pose des problèmes lorsque la table a déjà des valeurs nulles. Voir ma réponse

5 votes

Disponible également en 3.2. Il y a aussi un 4ème paramètre pour définir la valeur par défaut lorsque les valeurs sont nulles.

1 votes

Plus 1 pour change_column_null . Cependant, le commentaire de Rick Smith ci-dessus met en évidence un cas très valable.

73voto

Rick Smith Points 1066

Rails 4 (les autres réponses à Rails 4 posent problème) :

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

La modification d'une colonne contenant des valeurs NULL pour ne pas autoriser les NULL causera des problèmes. C'est exactement le type de code qui fonctionnera parfaitement dans votre configuration de développement et qui se plantera lorsque vous essaierez de le déployer sur votre site Web. LIVE production. Vous devez d'abord changer les valeurs NULL en quelque chose de valide et entonces interdire les NULL. La 4ème valeur dans change_column_null fait exactement cela. Voir documentation pour plus de détails.

De plus, je préfère généralement définir une valeur par défaut pour le champ afin de ne pas avoir à spécifier la valeur du champ à chaque fois que je crée un nouvel objet. J'ai inclus le code commenté pour le faire également.

3 votes

Pour Rails 4, cela semble être la réponse la plus précise et la plus complète, y compris le paramètre par défaut commenté.

4 votes

Si vous ajoutez une nouvelle colonne à une table et que vous voulez insérer de nouvelles valeurs pour null, mais que vous ne voulez pas ajouter une valeur par défaut pour la colonne, vous pouvez le faire dans votre migration : add_column :users, :admin, :string puis change_column_null(:admin, :string, false, "new_value_for_existing_records")

48voto

jessecurry Points 12114

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

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

Voir : changer_colonne

En fonction du moteur de la base de données, vous devrez peut-être utiliser l'option change_column_null

1 votes

Cela a fonctionné pour moi. J'utilise MySQL localement. Lorsque j'ai poussé et lancé l'application dans Heroku (Postgres), elle a craqué sur une colonne qui n'était pas nulle alors que je l'avais écrite nulle - à juste titre. Seul "change_column_null" fonctionne, je ne peux pas utiliser "change_column ... :null => false" sur MySql. Merci.

1 votes

Quelle a été votre migration après change_column_null ?

1 votes

Postges est plus stricte que MySQL -- je m'attendrais à ce qu'elle nécessite change_column_null .

12voto

piratebroadcast Points 121

Rails 4 :

def change
  change_column_null(:users, :admin, false )
end

1 votes

Veuillez fournir une description de vos réponses.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X