Migrasi rel: Membatalkan pengaturan default untuk sebuah kolom

190

Saya punya masalah, bahwa saya memiliki migrasi di Rails yang menetapkan pengaturan default untuk kolom, seperti contoh ini:

def self.up
  add_column :column_name, :bought_at, :datetime, :default => Time.now
end

Misalkan, saya ingin menghapus pengaturan default itu dalam migrasi nanti, bagaimana saya melakukannya dengan menggunakan migrasi rails?

Solusi saya saat ini adalah pelaksanaan perintah sql khusus dalam migrasi rails, seperti ini:

def self.up
  execute 'alter table column_name alter bought_at drop default'
end

Tapi saya tidak suka pendekatan ini, karena saya sekarang tergantung pada bagaimana database yang mendasari menafsirkan perintah ini. Jika terjadi perubahan pada basis data, kueri ini mungkin tidak berfungsi lagi dan migrasi akan rusak. Jadi, apakah ada cara untuk mengekspresikan pembatalan pengaturan default untuk kolom di rails?

wulfovitch
sumber

Jawaban:

387

Rails 5+

def change
  change_column_default( :table_name, :column_name, from: nil, to: false )
end

Rails 3 dan Rails 4

def up
  change_column_default( :table_name, :column_name, nil )
end

def down
  change_column_default( :table_name, :column_name, false )
end
Jeremy Mack
sumber
7
Di postgres, ini tidak akan benar-benar menjatuhkan default untuk CHARACTER VARYINGkolom, cukup atur NULL::character varying.
Attila O.
8
Di versi yang lebih baru, Anda dapat membuatnya reversibel. Misalnya: change_column_default(:table_name, :column_name, from: nil, to: false)
Markus
1
@ AttilaO. Saya sudah sukses berlari ALTER TABLE table_name ALTER COLUMN type DROP DEFAULT, tidak perlu mengaturnya NULLmenurut saya.
Eli Rose - REINSTATE MONICA
FYI, sepertinya versi reversibel yang menyebutkan @Mark ditambahkan di Rails 5+, jadi apa pun di bawahnya, Anda tidak akan dapat menggunakannya.
Joshua Pinter
23

Suara seperti Anda melakukan hal yang benar dengan Anda 'mengeksekusi', sebagai docs menunjukkan:

change_column_default(table_name, column_name, default)

Menetapkan nilai default baru untuk sebuah kolom. Jika Anda ingin menetapkan nilai default ke NULL, Anda kurang beruntung. Anda perlu # DatabaseStatements menjalankan sendiri pernyataan SQL yang sesuai. Contohnya

change_column_default(:suppliers, :qualification, 'new')
change_column_default(:accounts, :authorized, 1)
Serx
sumber
Terima kasih! Saya belum menemukan petunjuk ini di dokumen sendiri! Semoga mereka membangun dalam menjatuhkan nilai default ke migrasi di versi rel yang akan datang.
Wulfovitch
1
Ini tidak benar lagi pada Rails 3.1.0, cfr. apidock.com/rails/v3.1.0/ActiveRecord/ConnectionAdapters/…
asymmetric
14

Cuplikan berikut ini saya gunakan untuk membuat NULLkolom NOT NULL, tetapi lewati DEFAULTdi tingkat skema:

def self.up
  change_column :table, :column, :string, :null => false, :default => ""
  change_column_default(:table, :column, nil)
end
Alex Fortuna
sumber
Saya tidak melihat nilai tambah dalam jawaban ini karena yang diterima menyatakan hal yang sama.
Mosselman
-3

Rel 4

change_column :courses, :name, :string, limit: 100, null: false
Pembalasan Lesly
sumber
10
Yang ini menambahkan BUKAN kendala NULL, itu tidak ada hubungannya dengan DEFAULT
Extrapolator
tidak ada hubungannya dengan DEFAULT +1
Ivan Wang