it-swarm.com.de

Wie ändere ich eine nullfähige Spalte in einer Rails Migration in eine nicht nullfähige?

Ich habe in einer früheren Migration eine Datumsspalte erstellt und diese auf null gesetzt. Jetzt möchte ich es ändern, um nicht nullable zu sein. Wie gehe ich vor, wenn die Datenbank Nullzeilen enthält? Es ist in Ordnung, diese Spalten auf Time.now zu setzen, wenn sie derzeit null sind.

176
Kevin Pang

Wenn Sie es in einer Migration machen, könnten Sie es wahrscheinlich so machen:

# Make sure no null value exist
MyModel.where(date_column: nil).update_all(date_column: Time.now)

# Change the column to not allow null
change_column :my_models, :date_column, :datetime, null: false
189
DanneManne

In Rails 4 ist dies eine bessere (DRYer) Lösung:

change_column_null :my_models, :date_column, false

Um sicherzustellen, dass keine Datensätze mit NULL Werten in dieser Spalte vorhanden sind, können Sie einen vierten Parameter übergeben. Dies ist der Standardwert für Datensätze mit NULL Werten:

change_column_null :my_models, :date_column, false, Time.now
145
mrbrdo

Rails 4 (andere Rails 4 Antworten haben Probleme):

def change
  change_column_null(:users, :admin, false, <put a default value here> )
  # change_column(:users, :admin, :string, :default => "")
end

Das Ändern einer Spalte mit NULL-Werten, um NULL nicht zuzulassen, führt zu Problemen. Dies ist genau der Codetyp, der in Ihrem Entwicklungssetup gut funktioniert und dann abstürzt, wenn Sie versuchen, ihn in Ihrer [~ # ~] live [~ # ~] Produktion bereitzustellen. Sie sollten zuerst NULL-Werte in einen gültigen Wert ändern und then NULL-Werte nicht zulassen. Der 4. Wert in change_column_null macht genau das. Siehe Dokumentation für weitere Details.

Außerdem ziehe ich es im Allgemeinen vor, einen Standardwert für das Feld festzulegen, damit ich den Feldwert nicht jedes Mal angeben muss, wenn ich ein neues Objekt erstelle. Dazu habe ich auch den auskommentierten Code eingefügt.

66
Rick Smith

Erstellen Sie eine Migration mit einem change_column Anweisung mit einem :default => Wert.

change_column :my_table, :my_column, :integer, :default => 0, :null => false

Siehe: change_column

Abhängig vom Datenbankmodul müssen Sie möglicherweise change_column_null

32
jessecurry

Schienen 4:

def change
  change_column_null(:users, :admin, false )
end
11
piratebroadcast

In Rails 4.02 + gibt es laut docs keine Methode wie update_all mit 2 Argumenten. Stattdessen kann man diesen Code verwenden:

# Make sure no null value exist
MyModel.where(date_column: nil).update_all(date_column: Time.now)

# Change the column to not allow null
change_column :my_models, :date_column, :datetime, null: false
3
jmarceli

Sie können add_timestamps und null: false nicht verwenden, wenn Sie über vorhandene Datensätze verfügen. Hier ist die Lösung:

def change
  add_timestamps(:buttons, null: true)

  Button.find_each { |b| b.update(created_at: Time.zone.now, updated_at: Time.zone.now) }

  change_column_null(:buttons, :created_at, false)
  change_column_null(:buttons, :updated_at, false)
end
2