Ruby on Rails: Comment ajouter une contrainte non nulle à une colonne existante à l'aide d'une migration?

130

Dans mon application Rails (3.2), j'ai un tas de tables dans ma base de données mais j'ai oublié d'ajouter quelques contraintes non nulles. J'ai cherché sur Google mais je ne trouve pas comment écrire une migration qui ajoute non nul à une colonne existante.

TIA.

David Robertson
la source

Réponses:

93

Pour Rails 4+, la réponse de nates (en utilisant change_column_null ) est meilleure.

Pre-Rails 4, essayez change_column .

Dan Wich
la source
25
Soyez prudent avec cette approche - si vous aviez d'autres attributs à propos de cette colonne (par exemple une :limitcontrainte), vous devez répéter ces attributs lors de l'utilisation change_column, sinon ils seront perdus. Pour cette raison, je préfère utiliserchange_column_null
Nathan Wallace
Notez que cela génère un IrreversibleMigrationqui peut ne pas être ce que vous voulez.
Nic Nilov
@NicNilov parlez-vous de la réponse OU du commentaire de Nathan Wallace?
Mark
@Mark Je parlais de la réponse, désolé de ne pas être assez précis.
Nic Nilov
@NicNilov no dw Je pensais que même si je voulais juste vérifier :)
Marquez
274

Vous pouvez également utiliser change_column_null :

change_column_null :table_name, :column_name, false
nates
la source
8
Réponse la plus propre!
Josh Click
1
J'ai dû le changer pour un tas de colonnes et cela ne nécessite pas de spécifier le type de colonne pour chaque colonne, bien mieux!
Dorian
1
C'est la meilleure réponse. Dans ma base de données, j'ajoutais une contrainte nulle sur une colonne avec des valeurs nulles préexistantes. change_column ne mettrait pas à jour ces valeurs. Selon la documentation, change_column_null a une quatrième valeur facultative qui est la nouvelle valeur pour la mise à jour.
Merovex
Merci pour cela. Meilleure réponse.
Ryan Rebo
1
effet secondaire intéressant .... l'annulation de la migration définira le champ à l'opposé (faux -> vrai). Donc, si vous créez la migration pour plusieurs champs pour ajouter une contrainte nulle, et que certains champs avaient DÉJÀ une contrainte nulle, puis annulez la migration, cela SUPPRIMERA la contrainte nulle de tout champ qui l'avait déjà.
jpw
10

1) PREMIER: Ajouter une colonne avec la valeur par défaut

2) ALORS: supprimer la valeur par défaut

add_column :orders, :items, :integer, null: false, default: 0
change_column :orders, :items, :integer, default: nil
rndrfero
la source
2
c'est la solution correcte lorsque vous devez ajouter une nouvelle colonne qui n'est pas nulle, vous devez d'abord définir qu'elle a la valeur par défaut car SQLLite se plaindra (impossible d'ajouter une colonne NOT NULL avec la valeur par défaut NULL), puis supprimez-la!
Milan
2

Si vous l'utilisez sur un nouveau script / schéma de migration de création, voici comment nous pouvons le définir

class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
    t.string :name, null: false     # Notice here, NOT NULL definition
    t.string :email, null: false
    t.string :password, null: false
    t.integer :created_by
    t.integer :updated_by 

    t.datetime :created_at
    t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' }
   end
  end
end
Manjunath Reddy
la source