Menambahkan: default => true ke boolean di kolom Rails yang ada

160

Saya telah melihat beberapa pertanyaan (yaitu yang ini ) di sini di SO tentang menambahkan nilai boolean default ke kolom yang ada. Jadi saya mencoba change_columnsaran tetapi saya tidak boleh melakukannya dengan benar.

Saya mencoba:

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

Yang kembali -bash: change_column: command not found

Saya kemudian berlari:

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

...dan

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

Kemudian berlari rake db:migrate, tetapi nilai untuk :show_attributetetap nil. Dalam pertanyaan yang saya referensikan di atas tertulis di PostgreSQL Anda perlu memperbaruinya secara manual. Karena saya menggunakan PostgreSQL, saya menambahkan yang berikut ini dalam create_profilesmigrasi saya :

t.boolean :show_attribute, :default => true

Bisakah seseorang memberi tahu saya apa yang saya lakukan salah di sini?

tvalent2
sumber

Jawaban:

314

change_columnadalah metode ActiveRecord::Migration, jadi Anda tidak dapat menyebutnya seperti itu di konsol.

Jika Anda ingin menambahkan nilai default untuk kolom ini, buat migrasi baru:

rails g migration add_default_value_to_show_attribute

Kemudian dalam migrasi dibuat:

# 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

ATAU opsi yang lebih spesifik:

def up
    change_column_default :profiles, :show_attribute, true
end

def down
    change_column_default :profiles, :show_attribute, nil
end

Kemudian jalankan rake db:migrate.

Itu tidak akan mengubah apa pun menjadi catatan yang sudah dibuat. Untuk melakukan itu Anda harus membuat rake taskatau hanya masuk rails consoledan memperbarui semua catatan (yang saya tidak akan merekomendasikan dalam produksi).

Ketika Anda menambahkan t.boolean :show_attribute, :default => trueke create_profilesmigrasi, diharapkan tidak melakukan apa-apa. Hanya migrasi yang belum dijalankan yang dieksekusi. Jika Anda mulai dengan database baru, maka itu akan menetapkan default ke true.

Robin
sumber
2
Panggilan change_column itu harus dalam upmetode dalam migrasi, yang merupakan kelas baru yang akan dihasilkan dalam db / migrasi /. ( downMetode harus ditulis untuk membatalkan apa yang updilakukan.) Buat perubahan itu, lalu rake db:migrate.
rkb
Ahh, itu lebih masuk akal rkb. Terima kasih!
tvalent2
itu tidak bekerja untuk saya sampai saya menulis def self.updandef self.down
Kamil Szot
Anda mungkin menggunakan versi rel yang lebih lama. Saya pikir sintaks ini sudah ada sejak 3.1.
Robin
Dan di Rails 5, Anda meninggalkan _atribut sehingga seharusnya hanya mengatakan showatau apa pun nama kolomnya.
labirin
95

Sebagai variasi pada jawaban yang diterima, Anda juga dapat menggunakan change_column_defaultmetode ini dalam migrasi Anda:

def up
  change_column_default :profiles, :show_attribute, true
end

def down
  change_column_default :profiles, :show_attribute, nil
end

Rails API-docs

Sebastiaan Pouyet
sumber
1
Ini memastikan Anda tidak akan secara tidak sengaja mengubah salah satu properti kolom lainnya
Brian Low
1
Dan di Rails 5 Anda meninggalkan _atribut sehingga seharusnya hanya mengatakan showatau apa pun nama kolomnya.
labirin
1
@ labirin Apa maksud Anda? show_attribute adalah nama kolom, saya tidak berpikir rel 5 ada hubungannya dengan itu, kan?
Robin
34

Saya tidak yakin kapan ini ditulis, tetapi saat ini untuk menambah atau menghapus default dari kolom dalam migrasi, Anda dapat menggunakan yang berikut ini:

change_column_null :products, :name, false

Rel 5:

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

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

Rails 4.2:

change_column_default :products, :approved, false

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

Yang merupakan cara yang rapi untuk menghindari melihat melalui migrasi atau skema Anda untuk spesifikasi kolom.

Fbelanger
sumber
Hati-hati, ini dari dokumentasi Rails 5. Versi Rails 4.2 ini tidak menerima hash tapi persis default baru sebagai parameter ketiga. guide.rubyonrails.org/v4.2/…
Clamoris
Tentang Rails 5, melakukan keduanya tampaknya merupakan cara yang paling benar, misalnya null: falsedan default: :somethingpada dasarnya
Dorian
1

Jika Anda baru saja melakukan migrasi, Anda dapat mengembalikan dan kemudian melakukan migrasi lagi.

Untuk mengembalikan, Anda dapat melakukan langkah sebanyak yang Anda inginkan:

rake db:rollback STEP=1

Atau, jika Anda menggunakan Rails 5.2 atau yang lebih baru:

rails db:rollback STEP=1

Kemudian, Anda bisa melakukan migrasi lagi:

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

Jangan lupa rake db:migratedan jika Anda menggunakan herokuheroku run rake db:migrate

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

Tampaknya merupakan cara terbaik untuk menambahkan default ke kolom yang sudah ada yang tidak memiliki null: false .

Jika tidak:

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

Beberapa penelitian yang saya lakukan tentang ini:

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

Dorian
sumber
0

Jika Anda tidak ingin membuat file migrasi lain untuk perubahan kecil dan terbaru - dari Rails Console:

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

Kemudian keluar dan masukkan kembali konsol konsol, sehingga DB-Changes akan berlaku. Lalu, jika Anda melakukan ini ...

Profile.new()

Anda harus melihat nilai default "show_attribute" sebagai benar.

Untuk catatan yang ada, jika Anda ingin mempertahankan pengaturan "false" yang ada dan hanya memperbarui nilai "nil" ke default baru Anda:

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

Perbarui migrasi yang membuat tabel ini, sehingga build DB apa pun di masa mendatang akan memperbaikinya sejak awal. Jalankan juga proses yang sama pada instance DB yang digunakan.

Jika menggunakan metode "migrasi db baru", Anda dapat melakukan pembaruan dari nilai-nil yang ada dalam migrasi itu.

JosephK
sumber