Rails geçişinde varolan bir tabloya sütun ekleme


340

Bir :emailsütun (ilk iskele sırasında bu sütun eklemeyi unuttum) gereken bir kullanıcılar modeli var .

Geçiş dosyasını açtım ve ekledim t.string :email, yaptım rake db:migrateve anladım NoMethodError. Sonra satırı ekledim

add_column :users, :email, :string

tekrar rake db:migrate, tekrar NoMethodError. Burada bir adım eksik mi?

Düzenleme: İşte taşıma dosyası.

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

Yanıtlar:


574

Orijinal taşımanızı zaten çalıştırdıysanız (düzenlemeden önce), yeni bir taşıma oluşturmanız gerekir ( rails generate migration add_email_to_users email:stringhile yapar). Şu satırı içeren bir taşıma dosyası oluşturur: add_column :users, email, string Sonra bir yapın rake db:migrateve yeni taşıma işlemini çalıştırarak yeni sütunu oluşturun.

Henüz orijinal taşımayı çalıştırmadıysanız, bunu yapmaya çalıştığınız gibi düzenleyebilirsiniz. Geçiş kodunuz neredeyse mükemmel: sadece add_columnçizgiyi tamamen kaldırmanız gerekiyor (bu kod, tablo oluşturulmadan ve tablo oluşturma kodunuz zaten dahil edilecek şekilde güncellenmeden önce bir tabloya sütun eklemeye çalışıyor t.string :email).


6
Açıkça söylemek gerekirse çoğul mu kullanıyoruz? Yani öyle add_email_to_usersve DEĞİL add_email_to_user?
Purplejacket

9
Doğru. Rails içindeki tablo adları her zaman çoğuldur (DB kurallarına uyması için).
Ocak'ta camdez

2
rails db:migrateSon adım için de kullanabilirsiniz .
Dylan Vander Berg

Tablodaki belirli bir konumda yeni bir sütun oluşturmak mümkün mü? Örneğin, mevcut "e-posta" alanından hemen sonra yeni alan "durum" oluşturmak istiyorsam?
neeraj

2
@neeraj muhtemelen şimdiye kadar cevabınız var, ancak diğer arayanlar için, evet, örneğin t.string :column_x, limit: 10, after: :column_y(en azından 4 numaralı raylar için)
244an

124

Raylar konsolunda bu komutu kullanın

rails generate migration add_fieldname_to_tablename fieldname:string

ve

rake db:migrate

bu taşımayı yürütmek için


57

Bazen rails generate migration add_email_to_users email:stringböyle bir göç üretir

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

Bu durumda bir elle zorunda add_columniçin change:

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

Ve sonra koş rake db:migrate


1) rails generate migration add_email_to_users email:stringBu bundle exec rails cterminalden sonra mı yoksa terminal içinde mi yapılmalıdır ? 2) Sorguyu yürüttüğümüzde oluşturulan dosya nereye yerleştirilir?
19:18

28

Ayrıca yapabilirsin

rake db:rollback

Tablolara herhangi bir veri eklemediyseniz, daha sonra e-posta sütununu ekleyerek taşıma dosyasını düzenleyin ve ardından

rake db:migrate

Bu, sisteminizde raylar 3.1 ve üzeri kurulu ise çalışır.

Bunu yapmanın çok daha basit yolu, geçiş dosyasındaki değişikliğin olduğu gibi olmasına izin vermektir. kullanım

$rake db:migrate:redo

Bu, son geçişi geri alır ve tekrar taşır.


21

Bir sütun eklemek için şu adımları izlemem gerekiyordu:

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    Alternatif

    rails generate migration addFieldnameToTablename

    Taşıma oluşturulduktan sonra taşıma işlemini düzenleyin ve bu sütunun eklenmesini istediğiniz tüm özellikleri tanımlayın.

    Not : Rails içindeki tablo adları her zaman çoğuldur (DB kurallarına uyması için). Daha önce belirtilen adımlardan birini kullanan örnek-

    rails generate migration addEmailToUsers

  2. rake db:migrate

Veya

  1. Şemasını db/schema.rbSQL sorgusunda istediğiniz sütunları Ekle'den değiştirebilirsiniz.
  2. Bu komutu çalıştırın: rake db:schema:load

    Uyarı / Not

    Unutmayın, koşmak rake db:schema:loadotomatik olarak tablolarınızdaki tüm verileri siler.


Bunu yaptım, ama "iskele" yeniden yapmadım ve yeni sütun eklemedi. Bunu "otomatik olarak" nasıl yapabilirim?
John Wooten

John Wooten, İskele'yi silmek ve tekrar gözden geçirmek isteyebilirsiniz. Karşılık gelen taşıma işlemlerini de bırakın.
Afolabi Olaoluwa Akinwumi

not eklemek için: geçişi değiştirmeden şemayı değiştirmek, uygulamayı koruyan diğer geliştiricilerle sorunlar oluşturabilir.
BKSpurgeon

3

Bunu yaptığımda, orijinal taşıma işlemini yürütmek yerine, yalnızca yukarı bölümünde ekleme sütunu ve aşağı bölümünde bir bırakma sütunu ile yeni bir tane oluşturuyorum.

Orijinali değiştirebilir ve aralarında geçiş yaparsanız yeniden çalıştırabilirsiniz, ancak bu durumda bunun düzgün çalışmayan bir geçiş yaptığını düşünüyorum.

Şu anda yayınlandığı gibi, sütunu ekledikten sonra tabloyu oluşturuyorsunuz.

Sırayı değiştirirseniz işe yarayabilir. Veya mevcut bir taşımayı değiştirirken, ayrı bir ekleme sütunu yapmak yerine bunu oluşturma tablosuna eklemeniz yeterlidir.


1

force: trueTablonuz zaten varsa tabloyu kullanarak tablo sütunlarını zorlayabilirsiniz .

örnek :

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


0

Son taşıma işlemini şu yolla geri alabilirsiniz:

rake db:rollback STEP=1

veya bu belirli taşıma işlemini

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

ve dosyayı düzenleyip rake db:mirgatetekrar çalıştırın .



0

Ayrıca, sütundan önce veya aşağıdaki gibi bir sütundan sonra belirli bir konuma sütun ekleyebilirsiniz:

rails generate migration add_dob_to_customer dob:date

Taşıma dosyası şu durumlar dışında şu kodu oluşturur:: e-posta. sonra eklemeniz gerekir: e-posta veya önce: e-posta

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
end
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.