Ajouter une valeur par défaut à une colonne via une migration

276

Comment ajouter une valeur par défaut à une colonne qui existe déjà via une migration?

Toute la documentation que je peux trouver vous montre comment le faire si la colonne n'existe pas déjà mais dans ce cas elle existe.

Jon
la source

Réponses:

352

Voici comment procéder:

change_column :users, :admin, :boolean, :default => false

Mais certaines bases de données, comme PostgreSQL, ne mettront pas à jour le champ pour les lignes précédemment créées, alors assurez-vous de mettre à jour le champ de manière correcte lors de la migration.

Maurício Linhares
la source
14
Si vous avez besoin de migrations réversibles, placez-les dans un upbloc plutôt que dans un changebloc. Vous pouvez laisser le downbloc vide. Il ne ramènera pas la table à son état d'origine, mais la migration peut être annulée.
IAmNaN
1
Cela gardera-t-il les données intactes?
Marco Prins
2
Sur PostgreSQL, oui, je ne sais pas ce qui se passera sur les autres bases de données.
Maurício Linhares
1
Que voulez-vous dire lorsque vous dites "assurez-vous de mettre à jour le champ manuellement lors de la migration"? Comment fait-on cela?
David Argyle Thacker
7
Je l'ai essayé sur PostgreSQL et il a mis à jour les champs créés précédemment.
Aboozar Rajabi
190
change_column_default :employees, :foreign, false
Gazza
la source
1
@DenisLins Je suis d'accord avec vous, j'ai donc fait des recherches pour comprendre pourquoi cela pourrait ne pas être le cas, et il s'avère qu'il est possible qu'un adaptateur de base de données particulier ne le prenne pas en charge, car il est implémenté à ce niveau. La réponse acceptée est toujours le pari le plus sûr jusqu'à ce qu'elle soit implémentée dans le modèle abstrait. apidock.com/rails/ActiveRecord/ConnectionAdapters/…
natchiketa
5
En plus de cela, vous devez spécifier un from:et to:si vous voulez qu'il soit réversible :)
radubogdan
5
Utilisation fromet a toété ajouté dans Rails 5+ dans ce commit: github.com/rails/rails/pull/20018/files
Joshua Pinter
116

Pour Rails 4+ , utilisezchange_column_default

def change
  change_column_default :table, :column, value
end
csi
la source
1
Cela est particulièrement utile si vous avez une migration qui ajoute une colonne et définit des valeurs par défaut pour les enregistrements existants. Par exemple: def change `add_column: foos,: name, default:" quelque chose pour les valeurs existantes "` `change_column_default: foos,: name, default:" "`end
user1491929
2
Cette migration a un comportement étrange. Dans votre exemple, c'est irréversible. edgeguides.rubyonrails.org/active_record_migrations.html recommande de l'utiliser de cette façon: change_column_default :products, :approved, from: true, to: false- mais cela ne fonctionne pas aussi.
Ilya Krigouzov
ne peut pas revenir en arrière en utilisant cela?
aldrien.h
Habituellement, oui, pour presque toutes les clauses "Change", car tous les états précédents sont généralement explicites, tels que la présence d'une colonne, son type, etc. valide par défaut explicite précédemment. Comme il est courant que les valeurs par défaut ne soient pas définies, vous pourriez avoir un problème à cet endroit.
Elindor
48

En utilisant des def changemoyens, vous devez écrire des migrations réversibles. Et change_columnn'est pas réversible. Vous pouvez monter mais pas descendre car change_columnc'est irréversible.

Au lieu de cela, bien qu'il puisse s'agir de quelques lignes supplémentaires, vous devez utiliser def upetdef down

Donc, si vous avez une colonne sans valeur par défaut, vous devez le faire pour ajouter une valeur par défaut.

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: nil
end

Ou si vous souhaitez modifier la valeur par défaut d'une colonne existante.

def up
  change_column :users, :admin, :boolean, default: false
end

def down
  change_column :users, :admin, :boolean, default: true
end
bfcoder
la source
37

** Rails 4.X + **

À partir de Rails 4, vous ne pouvez pas générer de migration pour ajouter une colonne à une table avec une valeur par défaut. Les étapes suivantes ajoutent une nouvelle colonne à une table existante avec la valeur par défaut true ou false.

1. Exécutez la migration depuis la ligne de commande pour ajouter la nouvelle colonne

$ rails generate migration add_columnname_to_tablename columnname:boolean

La commande ci-dessus ajoutera une nouvelle colonne dans votre table.

2. Définissez la nouvelle valeur de colonne sur VRAI / FAUX en modifiant le nouveau fichier de migration créé.

class AddColumnnameToTablename < ActiveRecord::Migration
  def change
    add_column :table_name, :column_name, :boolean, default: false
  end
end

** 3. Pour effectuer les modifications dans votre table de base de données d'application, exécutez la commande suivante dans le terminal **

$ rake db:migrate
Praveen George
la source
En quoi est-ce différent des rails 3+ ou 2+?
Ruby Racer
2
Est-ce que quelqu'un sait si cela a été intégré dans Rails 5?
sambecker
9

Exécuter:

rails generate migration add_column_to_table column:boolean

Il va générer cette migration:

class AddColumnToTable < ActiveRecord::Migration
  def change
    add_column :table, :column, :boolean
  end
end

Définissez la valeur par défaut en ajoutant: default => 1

add_column: table,: column,: boolean,: default => 1

Courir:

rake db: migrer

axeltaglia
la source
2
Maintenant, la valeur par défaut de 1 n'est pas exactement un booléen;) De plus, cet exampe ajoute une nouvelle colonne, au lieu de changer la colonne existante, ce que l'OP voulait réaliser
radiospiel
@radiospiel En fait, 1 est aussi un booléen :)
kinduff
Vous devrez également créer un enregistrement dans la table de clés étrangères avec un ID de 1 pour que cela fonctionne, afin d'éviter le Key is not present in table error.
Promise Preston
-50

Voici ce que vous pouvez faire:

class Profile < ActiveRecord::Base
  before_save :set_default_val

  def set_default_val
    self.send_updates = 'val' unless self.send_updates
  end
end

EDIT: ... mais apparemment, c'est une erreur Rookie!

rookieRailer
la source
C'est mieux si vous définissez la valeur par défaut dans le schéma par rapport àbefore_save
rigelstpierre
6
Quelle terrible suggestion
svelandiag
d'accord, c'est vraiment terrible
Houcheng
3
aïe, vous avez eu beaucoup de chaleur pour faire quelque chose au niveau du modèle plutôt qu'au niveau de la base de données. -38 est un score légendaire.
nurettin
1
quelle erreur de débutant ... ;-)
webaholik