Menambahkan kolom ke tabel yang ada di migrasi Rails


340

Saya memiliki model Pengguna yang membutuhkan :emailkolom (saya lupa menambahkan kolom itu selama perancah awal).

Saya membuka file migrasi dan menambahkan t.string :email, melakukan rake db:migrate, dan mendapat NoMethodError. Lalu saya menambahkan baris

add_column :users, :email, :string

lagi rake db:migrate, lagi NoMethodError. Apakah saya kehilangan langkah di sini?

Sunting: ini file migrasi.

class CreateUsers < ActiveRecord::Migration  
  def self.up  
    add_column :users, :email, :string  
    create_table :users do |t|  
      t.string :username  
      t.string :email  
      t.string :crypted_password  
      t.string :password_salt  
      t.string :persistence_token  

      t.timestamps  
    end  
  end  

  def self.down  
    drop_table :users  
  end  
end

Jawaban:


574

Jika Anda sudah menjalankan migrasi asli Anda (sebelum mengeditnya), maka Anda perlu membuat migrasi baru ( rails generate migration add_email_to_users email:stringakan melakukan triknya). Ini akan membuat file migrasi yang berisi baris: add_column :users, email, string Kemudian lakukan rake db:migratedan itu akan menjalankan migrasi baru, membuat kolom baru.

Jika Anda belum menjalankan migrasi asli, Anda bisa mengeditnya, seperti yang Anda coba lakukan. Kode migrasi Anda hampir sempurna: Anda hanya perlu menghapus add_columnbaris sepenuhnya (kode itu mencoba menambahkan kolom ke tabel, sebelum tabel dibuat, dan kode pembuatan tabel Anda telah diperbarui untuk menyertakan t.string :emailpula).


6
Supaya jelas, kita menggunakan jamak? Jadi add_email_to_usersdan TIDAK add_email_to_user?
Purplejacket

9
Benar. Nama tabel dalam Rails selalu jamak (untuk mencocokkan konvensi DB).
camdez

2
Anda juga dapat menggunakan rails db:migrateuntuk langkah terakhir.
Dylan Vander Berg

Apakah mungkin untuk membuat kolom baru pada posisi tertentu dalam sebuah tabel. Misalnya jika saya ingin membuat "status" bidang baru setelah bidang "email" yang ada?
neeraj

2
@neeraj Anda mungkin sudah memiliki jawabannya sekarang tetapi untuk pencari lain, ya Anda bisa seperti dalam contoh t.string :column_x, limit: 10, after: :column_y(untuk Rails 4 setidaknya)
244an

124

Gunakan perintah ini di konsol rails

rails generate migration add_fieldname_to_tablename fieldname:string

dan

rake db:migrate

untuk menjalankan migrasi ini


57

Terkadang rails generate migration add_email_to_users email:stringmenghasilkan migrasi seperti ini

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
  end
end

Dalam hal ini Anda harus secara manual add_columnke change:

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :email, :string
  end
end

Dan kemudian jalankan rake db:migrate


1) Haruskah rails generate migration add_email_to_users email:stringini dijalankan setelah bundle exec rails catau hanya di dalam terminal? 2) Di mana file yang dihasilkan ditempatkan setelah kami menjalankan query?
sofs1

28

Anda juga bisa melakukannya

rake db:rollback

jika Anda belum menambahkan data apa pun ke tabel. Kemudian edit file migrasi dengan menambahkan kolom email ke dalamnya lalu panggil

rake db:migrate

Ini akan berfungsi jika Anda memiliki rel 3.1 dan seterusnya diinstal di sistem Anda.

Cara yang lebih sederhana untuk melakukannya adalah mengubah biarkan perubahan dalam file migrasi apa adanya. menggunakan

$rake db:migrate:redo

Ini akan mengembalikan migrasi terakhir dan memigrasikannya kembali.


21

Untuk menambahkan kolom, saya hanya harus mengikuti langkah-langkah ini:

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    Alternatif

    rails generate migration addFieldnameToTablename

    Setelah migrasi dibuat, kemudian edit migrasi dan tentukan semua atribut yang Anda inginkan untuk ditambahkan oleh kolom itu.

    Catatan : Nama tabel dalam Rails selalu jamak (untuk mencocokkan konvensi DB). Contoh menggunakan salah satu langkah yang disebutkan sebelumnya-

    rails generate migration addEmailToUsers

  2. rake db:migrate

Atau

  1. Anda dapat mengubah skema dari db/schema.rb, Tambahkan kolom yang Anda inginkan dalam kueri SQL.
  2. Jalankan perintah ini: rake db:schema:load

    Peringatan / Catatan

    Ingatlah bahwa, menjalankan rake db:schema:loadsecara otomatis menghapus semua data di tabel Anda.


Saya melakukan ini, tetapi tidak mengulangi "perancah" dan menambahkan kolom baru. Bagaimana saya bisa melakukan itu "secara otomatis"?
John Wooten

@ John Wooten, Anda mungkin ingin menghapus Scaffold dan menjalaninya lagi. Jatuhkan migrasi yang sesuai juga.
Afolabi Olaoluwa Akinwumi

untuk menambahkan catatan: mengubah skema tanpa mengubah migrasi dapat membuat masalah dengan pengembang lain yang mempertahankan aplikasi.
BKSpurgeon

3

Ketika saya sudah melakukan ini, daripada mengutak-atik migrasi asli, saya membuat yang baru dengan hanya menambahkan kolom di bagian atas dan kolom drop di bagian bawah.

Anda dapat mengubah yang asli dan memutarnya kembali jika Anda bermigrasi di antaranya, tetapi dalam kasus ini saya pikir itu membuat migrasi yang tidak akan berfungsi dengan baik.

Saat ini diposting, Anda menambahkan kolom dan kemudian membuat tabel.

Jika Anda mengubah urutannya mungkin berhasil. Atau, saat Anda memodifikasi migrasi yang ada, tambahkan saja ke tabel buat alih-alih melakukan kolom tambahkan yang terpisah.


1

Anda juga bisa memaksa kolom tabel dalam tabel menggunakan force: true, jika tabel Anda sudah ada.

contoh :

ActiveRecord::Schema.define(version: 20080906171750) do
  create_table "authors", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end

1

Anda juga dapat menggunakan metode change_table khusus dalam migrasi untuk menambahkan kolom baru:

change_table(:users) do |t|
  t.column :email, :string
end

0

Anda dapat mengembalikan migrasi terakhir dengan

rake db:rollback STEP=1

atau kembalikan migrasi khusus ini oleh

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

dan edit file, lalu jalankan rake db:mirgatekembali.



0

Anda juga dapat menambahkan kolom ke posisi tertentu menggunakan sebelum kolom atau setelah kolom seperti:

rails generate migration add_dob_to_customer dob:date

File migrasi akan menghasilkan kode berikut kecuali setelah:: email. Anda perlu menambahkan setelah:: email atau sebelum:: email

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
end
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.