Hinzufügen: default => true to boolean in der vorhandenen Rails-Spalte

160

Ich habe hier auf SO einige Fragen (nämlich diese ) zum Hinzufügen eines booleschen Standardwerts zu einer vorhandenen Spalte gesehen. Also habe ich den change_columnVorschlag ausprobiert , aber ich muss ihn nicht richtig machen.

Ich habe es versucht:

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

Welches kehrt zurück -bash: change_column: command not found

Ich rannte dann:

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

...und

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

Dann lief rake db:migrate, aber der Wert für :show_attributeblieb nil. In der Frage, auf die ich oben verwiesen habe, heißt es in PostgreSQL, dass Sie es manuell aktualisieren müssen. Da ich PostgreSQL verwende, habe ich bei meiner create_profilesMigration Folgendes hinzugefügt :

t.boolean :show_attribute, :default => true

Kann mir jemand sagen, was ich hier falsch mache?

tvalent2
quelle

Antworten:

314

change_columnist eine Methode von ActiveRecord::Migration, so dass Sie es nicht so in der Konsole nennen können.

Wenn Sie einen Standardwert für diese Spalte hinzufügen möchten, erstellen Sie eine neue Migration:

rails g migration add_default_value_to_show_attribute

Dann in der Migration erstellt:

# 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

ODER eine spezifischere Option:

def up
    change_column_default :profiles, :show_attribute, true
end

def down
    change_column_default :profiles, :show_attribute, nil
end

Dann renne rake db:migrate.

An den bereits erstellten Datensätzen wird nichts geändert. Dazu müssten Sie eine erstellen rake taskoder einfach in die gehen rails consoleund alle Datensätze aktualisieren (was ich in der Produktion nicht empfehlen würde).

Wenn Sie t.boolean :show_attribute, :default => trueder create_profilesMigration hinzugefügt haben , wird erwartet, dass sie nichts bewirkt hat. Es werden nur Migrationen ausgeführt, die noch nicht ausgeführt wurden. Wenn Sie mit einer neuen Datenbank beginnen, wird der Standardwert auf true gesetzt.

Robin
quelle
2
Dieser Aufruf von change_column sollte sich in der upMethode in der Migration befinden. Hierbei handelt es sich um eine neue Klasse, die in db / migrate / generiert wird. (Die downMethode sollte geschrieben werden, um rückgängig zu machen up.) Nehmen Sie diese Änderung dann vor rake db:migrate.
rkb
Ahh, das macht mehr Sinn rkb. Vielen Dank!
tvalent2
es funktionierte nicht für mich, bis ich schrieb def self.upunddef self.down
Kamil Szot
Sie verwenden dann wahrscheinlich eine ältere Version von Schienen. Ich denke, diese Syntax gibt es seit 3.1.
Robin
Und in Rails 5 lassen Sie das _attribute weg, damit es nur sagt showoder wie auch immer der Spaltenname lautet.
Labyrinth
95

Als Variation der akzeptierten Antwort können Sie die change_column_defaultMethode auch in Ihren Migrationen verwenden:

def up
  change_column_default :profiles, :show_attribute, true
end

def down
  change_column_default :profiles, :show_attribute, nil
end

Rails API-Dokumente

Sebastiaan Pouyet
quelle
1
Dies stellt sicher, dass Sie keine der anderen Spalteneigenschaften versehentlich ändern
Brian Low
1
Und in Rails 5 lassen Sie das Attribut _attribute weg, damit es nur sagt showoder wie auch immer der Spaltenname lautet.
Labyrinth
1
@ Labyrinth Was meinst du? show_attribute ist der Name der Spalte, ich glaube nicht, dass Rails 5 etwas damit zu tun hat, oder?
Robin
34

Ich bin nicht sicher, wann dies geschrieben wurde, aber um derzeit einen Standardwert zu einer Spalte in einer Migration hinzuzufügen oder daraus zu entfernen, können Sie Folgendes verwenden:

change_column_null :products, :name, false

Schienen 5:

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

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

Schienen 4.2:

change_column_default :products, :approved, false

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

Auf diese Weise können Sie vermeiden, dass Sie in Ihren Migrationen oder im Schema nach den Spaltenspezifikationen suchen.

fbelanger
quelle
Achtung, es stammt aus der Rails 5-Dokumentation. Die Rails 4.2-Version akzeptiert keinen Hash, aber genau den neuen Standard als dritten Parameter. guides.rubyonrails.org/v4.2/…
Clamoris
Über Rails 5 scheint beides der richtigste Weg zu sein, z. B. null: falseund im default: :somethingGrunde genommen
Dorian
1

Wenn Sie gerade eine Migration durchgeführt haben, können Sie ein Rollback durchführen und die Migration dann erneut durchführen.

Zum Rollback können Sie so viele Schritte ausführen, wie Sie möchten:

rake db:rollback STEP=1

Oder wenn Sie Rails 5.2 oder höher verwenden:

rails db:rollback STEP=1

Dann können Sie die Migration einfach erneut durchführen:

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

Vergiss nicht rake db:migrateund wenn du Heroku verwendestheroku run rake db:migrate

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

Scheint der beste Weg zu sein, einer vorhandenen Spalte, die noch keine hat, einen Standard hinzuzufügen null: false.

Andernfalls:

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

Einige Nachforschungen, die ich dazu angestellt habe:

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

Dorian
quelle
0

Wenn Sie keine weitere Migrationsdatei für eine kleine, kürzlich vorgenommene Änderung erstellen möchten - über die Rails-Konsole:

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

Beenden Sie dann die Rails-Konsole und geben Sie sie erneut ein, damit die DB-Änderungen wirksam werden. Dann, wenn Sie dies tun ...

Profile.new()

Sie sollten den Standardwert "show_attribute" als true sehen.

Wenn Sie für vorhandene Datensätze vorhandene "falsche" Einstellungen beibehalten und nur "Null" -Werte auf Ihren neuen Standardwert aktualisieren möchten:

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

Aktualisieren Sie die Migration, mit der diese Tabelle erstellt wurde, damit zukünftige Builds der Datenbank sie von Anfang an erhalten. Führen Sie denselben Prozess auch auf allen bereitgestellten Instanzen der Datenbank aus.

Wenn Sie die Methode "Neue Datenbankmigration" verwenden, können Sie vorhandene Nullwerte in dieser Migration aktualisieren.

JosephK
quelle