Aggiunta: default => true a booleano nella colonna Rails esistente


160

Ho visto alcune domande (in particolare questa ) qui su SO sull'aggiunta di un valore booleano predefinito a una colonna esistente. Quindi ho provato il change_columnsuggerimento ma non devo farlo nel modo giusto.

Provai:

$ change_column :profiles, :show_attribute, :boolean, :default => true

Che ritorna -bash: change_column: command not found

Ho quindi eseguito:

$ rails g change_column :profiles, :show_attribute, :boolean, :default => true

...e

$ rails change_column :profiles, :show_attribute, :boolean, :default => true

Quindi ha funzionato rake db:migrate, ma il valore per è :show_attributerimasto nil. Nella domanda a cui ho fatto riferimento sopra, in PostgreSQL è indicato che è necessario aggiornarlo manualmente. Dal momento che sto usando PostgreSQL ho aggiunto quanto segue nella mia create_profilesmigrazione:

t.boolean :show_attribute, :default => true

Qualcuno può dirmi cosa sto facendo di sbagliato qui?

Risposte:


314

change_columnè un metodo di ActiveRecord::Migration, quindi non puoi chiamarlo così nella console.

Se si desidera aggiungere un valore predefinito per questa colonna, creare una nuova migrazione:

rails g migration add_default_value_to_show_attribute

Quindi nella migrazione creata:

# That's the more generic way to change a column
def up
  change_column :profiles, :show_attribute, :boolean, default: true
end

def down
  change_column :profiles, :show_attribute, :boolean, default: nil
end

O un'opzione più specifica:

def up
    change_column_default :profiles, :show_attribute, true
end

def down
    change_column_default :profiles, :show_attribute, nil
end

Quindi corri rake db:migrate.

Non cambierà nulla nei record già creati. Per fare ciò dovresti creare un rake tasko semplicemente andare in rails consolee aggiornare tutti i record (che non consiglierei in produzione).

Quando hai aggiunto t.boolean :show_attribute, :default => truealla create_profilesmigrazione, si prevede che non abbia fatto nulla. Vengono eseguite solo le migrazioni che non sono già state eseguite. Se hai iniziato con un nuovo database, imposta il valore predefinito su true.


2
Quella chiamata change_column dovrebbe essere nel upmetodo nella migrazione, che è una nuova classe che verrà generata in db / migrate /. (Il downmetodo dovrebbe essere scritto per annullare ciò che upfa.) Apportare tale modifica, quindi rake db:migrate.
rkb,

Ahh, ha più senso rkb. Grazie!
tvalent2,

non ha funzionato per me fino a quando non ho scritto def self.upedef self.down
Kamil Szot

Probabilmente stai usando una versione precedente di binari allora. Penso che questa sintassi sia presente dal 3.1.
Robin

E in Rails 5, lasci il _attribute quindi dovrebbe solo dire showo qualunque sia il nome della colonna.
labirinto

95

Come variante della risposta accettata, puoi anche utilizzare il change_column_defaultmetodo nelle tue migrazioni:

def up
  change_column_default :profiles, :show_attribute, true
end

def down
  change_column_default :profiles, :show_attribute, nil
end

Documenti API di Rails


1
Questo ti assicura di non modificare accidentalmente nessuna delle altre proprietà della colonna
Brian Low,

1
E in Rails 5 lasci l'attributo _ quindi dovrebbe semplicemente dire showo qualunque sia il nome della colonna.
labirinto

1
@labyrinth Che vuoi dire? show_attribute è il nome della colonna, non credo che rails 5 abbia qualcosa a che fare con questo, giusto?
Robin,

34

Non sono sicuro quando è stato scritto, ma al momento per aggiungere o rimuovere un valore predefinito da una colonna in una migrazione, è possibile utilizzare quanto segue:

change_column_null :products, :name, false

Rotaie 5:

change_column_default :products, :approved, from: true, to: false

http://edgeguides.rubyonrails.org/active_record_migrations.html#changing-columns

Rotaie 4.2:

change_column_default :products, :approved, false

http://guides.rubyonrails.org/v4.2/active_record_migrations.html#changing-columns

Il che è un modo semplice per evitare di esaminare le migrazioni o lo schema per le specifiche della colonna.


Attenzione, proviene dalla documentazione di Rails 5. La versione Rails 4.2 di questo non accetta l'hash ma esattamente il nuovo default come terzo parametro. guide.rubyonrails.org/v4.2/…
Clamoris,

A proposito di Rails 5, fare entrambe le cose sembra essere il modo più corretto, ad esempio null: falsee default: :somethingsostanzialmente
Dorian,


1

Se hai appena effettuato una migrazione, puoi eseguire il rollback e quindi eseguire nuovamente la migrazione.

Per eseguire il rollback puoi eseguire tutti i passaggi che desideri:

rake db:rollback STEP=1

Oppure, se si utilizza Rails 5.2 o versioni successive:

rails db:rollback STEP=1

Quindi, puoi semplicemente eseguire nuovamente la migrazione:

def change
  add_column :profiles, :show_attribute, :boolean, default: true
end

Non dimenticare di rake db:migratee se stai usando herokuheroku run rake db:migrate


0
change_column :things, :price_1, :integer, default: 123, null: false

Sembra essere il modo migliore per aggiungere un valore predefinito a una colonna esistente che non ha null: falsegià.

Altrimenti:

change_column :things, :price_1, :integer, default: 123

Alcune ricerche che ho fatto su questo:

https://gist.github.com/Dorian/417b9a0e1a4e09a558c39345d50c8c3b


0

Se non si desidera creare un altro file di migrazione per una piccola e recente modifica, da Rails Console:

ActiveRecord::Migration.change_column :profiles, :show_attribute, :boolean, :default => true

Quindi uscire e accedere nuovamente alla console delle rotaie, in modo che le modifiche al DB siano attive. Quindi, se lo fai ...

Profile.new()

Dovresti vedere il valore predefinito "show_attribute" come vero.

Per i record esistenti, se si desidera preservare le impostazioni "false" esistenti e aggiornare solo i valori "zero" al nuovo valore predefinito:

Profile.all.each{|profile| profile.update_attributes(:show_attribute => (profile.show_attribute == nil ? true : false))  }

Aggiorna la migrazione che ha creato questa tabella, in modo che eventuali build future del DB lo ottengano fin dall'inizio. Esegui anche lo stesso processo su qualsiasi istanza distribuita del DB.

Se si utilizza il metodo "nuova migrazione db", è possibile eseguire l'aggiornamento di valori nil esistenti in tale migrazione.

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.