Aggiungi un valore predefinito a una colonna tramite una migrazione


283

Come si aggiunge un valore predefinito a una colonna già esistente tramite una migrazione?

Tutta la documentazione che posso trovare ti mostra come fare se la colonna non esiste già ma in questo caso sì.

Risposte:


359

Ecco come dovresti farlo:

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

Ma alcuni database, come PostgreSQL, non aggiorneranno il campo per le righe create in precedenza, quindi assicurati di aggiornare manualmente il campo anche durante la migrazione.


14
Se hai bisogno di migrazioni reversibili, inseriscile in un upblocco anziché in un changeblocco. Puoi lasciare il downblocco vuoto. Non ripristinerà la tabella alla condizione originale ma la migrazione può essere annullata.
IAmNaN

1
Ciò manterrà i dati intatti?
Marco Prins

2
Su PostgreSQL, sì, non so cosa succederà su altri database.
Maurício Linhares

1
Cosa intendi quando dici "assicurati di aggiornare il campo manualmente durante la migrazione"? Come si fa a farlo?
David Argyle Thacker

7
L'ho provato su PostgreSQL e ha aggiornato i campi creati in precedenza.
Aboozar Rajabi

192
change_column_default :employees, :foreign, false

1
@DenisLins Sono d'accordo con te, quindi ho fatto alcune ricerche per capire perché potrebbe non esserlo, e si scopre che esiste la possibilità che un particolare adattatore di database non lo supporti, poiché è implementato a quel livello. La risposta accettata è ancora la scommessa più sicura finché non viene implementata nel modello astratto. apidock.com/rails/ActiveRecord/ConnectionAdapters/…
natchiketa

5
Oltre a ciò, è necessario specificare un from:e to:se si desidera che sia reversibile :)
radubogdan

5
Usando fromed è tostato aggiunto in Rails 5+ in questo commit: github.com/rails/rails/pull/20018/files
Joshua Pinter

119

Per Rails 4+ , usachange_column_default

def change
  change_column_default :table, :column, value
end

1
Questo è ottimo soprattutto se hai una migrazione che aggiunge una colonna e imposta i valori predefiniti per i record esistenti. Ad esempio: def change `add_column: foos,: name, default:" qualcosa per i valori esistenti "` `change_column_default: end
foos,:

3
Questa migrazione ha uno strano comportamento. Nel tuo esempio è irreversibile. edgeguides.rubyonrails.org/active_record_migrations.html consiglia di usarlo in questo modo: change_column_default :products, :approved, from: true, to: false- ma anche non funziona.
Ilya Krigouzov

non è possibile eseguire il rollback utilizzando quello?
aldrien.h

Di solito sì, per quasi tutte le clausole "Modifica", poiché tutti gli stati precedenti sono solitamente espliciti, come la presenza di una colonna, il suo tipo, ecc. La modifica può essere annullata come mostrato lì se e solo se c'era un valore predefinito esplicito valido in precedenza. Poiché è comune che i valori predefiniti non siano definiti, potresti avere un problema lì.
Elindor

49

Usare def changesignifica che dovresti scrivere migrazioni reversibili. E change_columnnon è reversibile. Puoi salire ma non puoi scendere, poiché change_columnè irreversibile.

Invece, sebbene possano essere un paio di righe in più, dovresti usare def upedef down

Quindi, se hai una colonna senza valore predefinito, dovresti farlo per aggiungere un valore predefinito.

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

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

O se desideri modificare il valore predefinito per una colonna esistente.

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

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

40

** Rotaie 4.X + **

A partire da Rails 4 non è possibile generare una migrazione per aggiungere una colonna a una tabella con un valore predefinito, i passaggi seguenti aggiungono una nuova colonna a una tabella esistente con valore predefinito true o false.

1. Eseguire la migrazione dalla riga di comando per aggiungere la nuova colonna

$ rails generate migration add_columnname_to_tablename columnname:boolean

Il comando precedente aggiungerà una nuova colonna nella tabella.

2. Impostare il valore della nuova colonna su VERO / FALSO modificando il nuovo file di migrazione creato.

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

** 3. Per apportare le modifiche alla tabella del database dell'applicazione, eseguire il seguente comando nel terminale **

$ rake db:migrate

In che modo è diverso da rails 3+ o 2+?
Ruby Racer

3
Qualcuno sa se questo è stato incorporato in Rails 5?
sambecker

@sambecker So che potrei essere un po 'in ritardo nel rispondere al tuo commento, ma per me funziona su Rails 6.0.3.1
Mathyou

@Mathyou buono a sapersi. In Rails 6 una nuova tabella può avere colonne con valori predefiniti? O è ancora una migrazione separata?
sambecker

9

Eseguire:

rails generate migration add_column_to_table column:boolean

Genererà questa migrazione:

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

Imposta il valore predefinito aggiungendo: default => 1

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

Correre:

rake db: migrate


2
Ora il valore predefinito di 1 non è esattamente un booleano;) Inoltre, questo esempio aggiunge una nuova colonna, invece di modificare la colonna esistente, che è ciò che l'OP voleva ottenere
radiospiel

@radiospiel In realtà, anche 1 è un booleano :)
kinduff

Dovrai anche creare un record nella tabella della chiave esterna con un ID 1 affinché funzioni, per evitare il file Key is not present in table error.
Promise Preston il

-52

Questo è quello che puoi fare:

class Profile < ActiveRecord::Base
  before_save :set_default_val

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

EDIT: ... ma a quanto pare questo è un errore Rookie!


È meglio se imposti il ​​valore predefinito nello schema vs come abefore_save
rigelstpierre

6
Che suggerimento terribile
svelandiag

d'accordo, è davvero terribile
Houcheng

3
ahi, hai molto calore per fare qualcosa a livello di modello invece che a livello di database. -38 è una partitura leggendaria.
nurettin

1
che errore da
principiante
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.