Ruby on Rails geçişinde bir veritabanı sütununu nasıl yeniden adlandırabilirim?


Yanıtlar:


2308
rename_column :table, :old_column, :new_column

Bunu yapmak için muhtemelen ayrı bir taşıma oluşturmak isteyeceksiniz. ( FixColumnNameİstediğiniz gibi yeniden adlandırın .):

script/generate migration FixColumnName
# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb

Ardından, isteğinizi yapmak için taşıma işlemini düzenleyin:

# db/migrate/xxxxxxxxxx_fix_column_name.rb
class FixColumnName < ActiveRecord::Migration
  def self.up
    rename_column :table_name, :old_column, :new_column
  end

  def self.down
    # rename back if you need or do something else or do nothing
  end
end

Rails 3.1 için:

, İken upve downyöntemler hala geçerli, 3.1 bir alan Raylar change"için veritabanı geçiş ve göç ayrı aşağı yöntemi yazmaya gerek kalmadan döndürülüyor ne zaman tersine çevirmek için nasıl bilir" bu yöntemi.

Daha fazla bilgi için bkz. " Aktif Kayıt Taşımaları ".

rails g migration FixColumnName

class FixColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

Yeniden adlandırılacak bir sürü sütununuz varsa veya tablo adını tekrar tekrar tekrarlamanız gereken bir şey varsa:

rename_column :table_name, :old_column1, :new_column1
rename_column :table_name, :old_column2, :new_column2
...

change_tableİşleri biraz daha temiz tutmak için kullanabilirsiniz :

class FixColumnNames < ActiveRecord::Migration
  def change
    change_table :table_name do |t|
      t.rename :old_column1, :new_column1
      t.rename :old_column2, :new_column2
      ...
    end
  end
end

Sonra db:migrateher zamanki gibi ya da işinizle ilgili.


Raylar 4 için:

Bir oluştururken Migrationbir sütun yeniden adlandırılması için, 4, bir oluşturur raylar changeyerine yöntemi upve downyukarıda bölümünde belirtildiği gibi. Oluşturulan changeyöntem:

$ > rails g migration ChangeColumnName

aşağıdakine benzer bir taşıma dosyası oluşturur:

class ChangeColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

24
self.down her zaman self.up'ın tam tersi olmalıdır, bu nedenle "başka bir şeye ihtiyacınız varsa veya bir şey yapıyorsanız ya da hiçbir şey yapmazsanız" gerçekten önerilmez. Şunu yapın: rename_column: table_name,: new_column,: old_column
Luke Griffiths

3
Yaptığınız şeyi geri döndürmek normal bir uygulama olsa da, "her zaman zıt olmalı" self.updemem . İçinde göçünüzün bağlamına bağlıdır. Sadece "karşıt" ı koymak "doğru" aşağı göç olmayabilir. self.down
nowk

23
Rails 3.1'de def self.upve def self.downile değiştirebilirsiniz ve def changegeri almayı bilir.
Turadg

2
Turadg - * çoğu zaman nasıl geri alınacağını bilecektir. Ben bulmak changeo kadar kullanma eğiliminde, yöntem tam kanıtı olmamasına upve downkarmaşık taşıma işlemlerinde yöntemleri.
JellyFishBoy

6
Yeniden adlandırma dizini kaldırır mı?
Sung Cho

68

Kanımca, bu durumda, kullanmak rake db:rollback, daha sonra geçişinizi düzenlemek ve tekrar çalıştırmak daha iyidir rake db:migrate.

Ancak, sütunda kaybetmek istemediğiniz verileriniz varsa kullanın rename_column.


34
"Birinden oluşan bir ekipte" bile, uygulamanızın birden fazla örneğini çalıştırıyorsanız, örneğin farklı ortamlarda veya birden çok bilgisayarda vb. Düzenlenmiş taşıma işlemlerini yönetmek büyük bir acıdır. Bir taşıma işlemini yalnızca yeni oluşturduğumda ve bunun yanlış olduğunu fark ettim ve henüz tam anlamıyla başka bir yerde çalıştırmadıysam düzenlerim .
Yetanotherjosh

1
Bundan sonra sunucuyu yeniden başlatmak zorunda kaldım.
Muhammad Hewedy

7
Bu teknik yalnızca değişikliklerinizin üretim dalınızla birleştirilmediği ve diğerlerinin veri kalıcılığına bağlı olmadığı bir durumda kullanılmalıdır. Çoğu üretim koşulunda, bu tercih edilen yöntem DEĞİLDİR.
Collin Graves

4
asla böyle şeyler yapmayın.
new2cpp

4
Ekibime şunu söylemekten hoşlanıyorum: 'Göçler ücretsiz' Vahşi doğada yayınlanan bir göçü düzenleme maliyeti yüksektir: Bir keresinde başka bir ekip üyesini fark etmeden önce kodumun neden çalışmadığını öğrenmek için birkaç saat geçirdim geri dönüp zaten yürüttüğüm bir göçü düzenledi. Bu nedenle mevcut bir taşıma işlemini düzenlemeyin, şemayı değiştirmek için yeni bir tane kullanın, çünkü ... ... 'Taşıma işlemleri ücretsizdir!' (bu kesinlikle doğru değil, ama bu noktaya işaret ediyor)
TerryS

31

Sütun zaten verilerle doldurulmuş ve üretimde yaşıyorsa, taşıma işlemlerini beklerken üretimde aksama süresini önlemek için adım adım bir yaklaşım öneriyorum.

İlk olarak, yeni ad (lar) içeren sütunlar eklemek ve bunları eski sütun adındaki değerlerle doldurmak için bir db geçişi oluştururdum.

class AddCorrectColumnNames < ActiveRecord::Migration
  def up
    add_column :table, :correct_name_column_one, :string
    add_column :table, :correct_name_column_two, :string

    puts 'Updating correctly named columns'
    execute "UPDATE table_name SET correct_name_column_one = old_name_column_one, correct_name_column_two = old_name_column_two"
    end
  end

  def down
    remove_column :table, :correct_name_column_one
    remove_column :table, :correct_name_column_two
  end
end

Sonra sadece bu değişikliği yapardım ve değişikliği üretime iterdim.

git commit -m 'adding columns with correct name'

Sonra taahhüt üretime girdiğinde, koşardım.

Production $ bundle exec rake db:migrate

Sonra eski sütun adını yeni sütun adına başvuran tüm görünümleri / denetleyicileri güncelleştiririm. Test paketimden geçin ve sadece bu değişiklikleri yapın. (Yerel olarak çalıştığından ve önce tüm testleri geçtikten sonra!)

git commit -m 'using correct column name instead of old stinky bad column name'

Sonra bu taahhüdü üretime iterdim.

Bu noktada, orijinal sütunu, taşımanın kendisiyle ilişkili herhangi bir kesinti süresi hakkında endişelenmeden kaldırabilirsiniz.

class RemoveBadColumnNames < ActiveRecord::Migration
  def up
    remove_column :table, :old_name_column_one
    remove_column :table, :old_name_column_two
  end

  def down
    add_column :table, :old_name_column_one, :string
    add_column :table, :old_name_column_two, :string
  end
end

Ardından bu son geçişi üretime aktarın ve bundle exec rake db:migratearka planda çalıştırın .

Bunun bir süreçle biraz daha ilgilendiğinin farkındayım, ancak bunu üretim göçümle ilgili sorunlardan daha çok tercih ederim.


2
Bunun arkasındaki düşünceyi seviyorum ve yanıtınızı + 1'leyecektim ama veri güncellemesinin yürütülmesi çok uzun zaman alacaktı, çünkü raylardan geçiyor ve her seferinde bir satır yapıyor. Doğru adlandırılmış sütunları güncellemek için ham sql ifadeleriyle taşıma çok daha hızlı yürütülür. Örneğin, ilk db geçiş komut dosyasında, yinelenen sütun adlarını ekledikten sonra, execute "Update table_name set correct_name_column_one = old_name_column_one"
Gui Weinmann

1
@ mr.ruh.roh ^ Tamamen katılıyorum, ilk etapta bunu yazmış olmalı. Tek bir verimli sql bildirisini yansıtacak şekilde düzenledim. Sağlık kontrolü için teşekkürler.
Paul Pettengill

2
Yeni tabloya geçmek ve yeni tabloyu kullanmak için kodu güncellemek arasındaki girişlerde ne olur? Potansiyel olarak taşınmamış verileriniz kalmamış olabilir mi?
Stefan Dorunga

1
bu 'güvenli' bir cevap olsa da, eksik olduğunu hissediyorum. Buradaki birçok insan bunu yapmadığını söylüyor -neden? verinin kalıcılığı. Ve bu geçerli. Muhtemelen hedefi başarmanın en az acı verici yolu, yeni alanlar oluşturmak, eski sütunlardaki verilerle doldurmak, denetleyicileri ayarlamaktır. Eski sütunları silmek istiyorsanız, kesinlikle görünümleri düzenlemeniz gerekir. Onları tutmanın maliyeti ekstra db alanı ve denetleyicide bazı yinelenen çaba. Böylece ödünleşimler açıktır.
Jerome


18

Bir taşıma dosyası oluşturmak için aşağıdaki komutu çalıştırın:

rails g migration ChangeHasedPasswordToHashedPassword

Sonra db/migrateklasörde oluşturulan dosyaya rename_columnaşağıdaki gibi yazın:

class ChangeOldCoulmnToNewColumn < ActiveRecord::Migration
  def change
     rename_column :table_name, :hased_password, :hashed_password
  end
end

14

API'dan:

rename_column(table_name, column_name, new_column_name)

Bir sütunu yeniden adlandırır, ancak türü ve içeriği aynı tutar.


12

Ruby on Rails'in bazı sürümleri geçiş için yukarı / aşağı yöntemini destekler ve geçişinizde yukarı / aşağı yöntemi varsa, o zaman:

def up
    rename_column :table_name, :column_old_name, :column_new_name
end

def down
    rename_column :table_name, :column_new_name, :column_old_name
end

Taşıma işleminizde changeyöntem varsa , o zaman:

def change
    rename_column :table_name, :column_old_name, :column_new_name
end

Daha fazla bilgi için taşıyabilirsiniz: Ruby on Rails - Taşıma veya Aktif Kayıt Taşıma .


11

Kodunuzu diğeri paylaşılmaz, o zaman en iyi seçenek sadece yapmaktır rake db:rollback sonra göç ve içinde sütun adını düzenleyin rake db:migrate. Bu kadar

Sütunu yeniden adlandırmak için başka bir taşıma yazabilirsiniz

 def change
    rename_column :table_name, :old_name, :new_name
  end

Bu kadar.


rake db:rollbackharika bir öneri. Ama dediğin gibi, sadece göç henüz itilmemişse.
danielricecodes

9

Alternatif bir seçenek olarak, taşıma fikriyle evli değilseniz, ActiveRecord için ad değişikliklerini sizin için otomatik olarak ele alan Datamapper stili vardır. Tek yapmanız gereken modelinizdeki sütun adını değiştirmek (ve Model.auto_upgrade! ' İ model.rb'nin altına yerleştirdiğinizden emin olun ) ve viyola! Veritabanı anında güncellenir.

https://github.com/DAddYE/mini_record

Not: Çakışmaları önlemek için db / schema.rb'yi tıklamanız gerekir.

Hala beta aşamalarında ve açıkçası herkes için değil ama yine de zorlayıcı bir seçim (şu anda bunu sorun olmayan iki önemsiz üretim uygulamasında kullanıyorum)


8

Sütun adlarını değiştirmeniz gerekirse, yinelenen bir sütun adı hatasını önlemek için bir yer tutucu oluşturmanız gerekir . İşte bir örnek:

class SwitchColumns < ActiveRecord::Migration
  def change
    rename_column :column_name, :x, :holder
    rename_column :column_name, :y, :x
    rename_column :column_name, :holder, :y
  end
end

7

Mevcut veriler sizin için önemli değilse, orijinal taşıma işleminizi aşağıdakileri kullanarak silebilirsiniz:

rake db:migrate:down VERSION='YOUR MIGRATION FILE VERSION HERE'

Tırnak işaretleri olmadan, orijinal taşımada değişiklikler yapın ve yukarı taşıma işlemini şu şekilde tekrar çalıştırın:

rake db:migrate

6

Yeni bir taşıma oluşturun ve bir blokta rename_columnaşağıdaki gibi kullanın .

rename_column :your_table_name, :hased_password, :hashed_password

6

Ruby on Rails 4 için:

def change
    rename_column :table_name, :column_name_old, :column_name_new
end

5

Manuel olarak aşağıdaki yöntemi kullanabiliriz:

Taşıma işlemini manuel olarak düzenleyebiliriz:

  • Açık app/db/migrate/xxxxxxxxx_migration_file.rb

  • Güncelleme hased_passwordiçinhashed_password

  • Aşağıdaki komutu çalıştırın

    $> rake db:migrate:down VERSION=xxxxxxxxx

Ardından taşıma işleminizi kaldıracak:

$> rake db:migrate:up VERSION=xxxxxxxxx

Güncellenen değişiklikle taşıma işleminizi ekleyecektir.


sütun zaten yayındaysa, verileri kaybedebileceğinizden güvenli olmayacaktır. ancak yeni sütun ve / veya tablo için yapabilir.
Tejas Patel

5

Taşıma dosyasını oluşturun:

rails g migration FixName

# Db / migrate / xxxxxxxxxx.rb oluşturur

İsteğinizi yapmak için taşıma işlemini düzenleyin.

class FixName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

5

Çalıştır rails g migration ChangesNameInUsers(ya da adlandırmak istersen)

Sadece oluşturulduktan göç dosyasını açın ve (arada yönteminde bu satırı ekleyin def changeve end):

rename_column :table_name, :the_name_you_want_to_change, :the_new_name

Dosyayı kaydedin rake db:migrateve konsolda çalıştırın

schema.dbVeritabanında adın gerçekten değişip değişmediğini görmek için göz atın !

Bu yardımcı olur umarım :)


5

Diyelim KISS . Tek yapmanız gereken üç basit adım. Rails 5.2 için aşağıdakiler geçerlidir .

1. Taşıma Oluşturma

  • rails g migration RenameNameToFullNameInStudents

  • rails g RenameOldFieldToNewFieldInTableName- bu şekilde daha sonra kod tabanının sahiplerine mükemmel bir şekilde açıktır. (tablo adı için çoğul kullanın).

2. Taşımayı düzenleyin

# I prefer to explicitly write theyukarı andaşağımethods.

# ./db/migrate/20190114045137_rename_name_to_full_name_in_students.rb

class RenameNameToFullNameInStudents < ActiveRecord::Migration[5.2]
  def up
    # rename_column :table_name, :old_column, :new_column
    rename_column :students, :name, :full_name
  end

  def down
            # Note that the columns are reversed
    rename_column :students, :full_name, :name
  end
end

3. Taşıma işlemlerinizi yürütün

rake db:migrate

Ve yarışlara gidiyorsun!


4
$:  rails g migration RenameHashedPasswordColumn
invoke  active_record
      create    db/migrate/20160323054656_rename_hashed_password_column.rb

Bu taşıma dosyasını açın ve aşağıdaki gibi değiştirin (Orijinal belgenizi girin table_name)

class  RenameHashedPasswordColumn < ActiveRecord::Migration
  def change
    rename_column :table_name, :hased_password, :hashed_password
  end
end

4
 def change
    rename_column :table_name, :old_column_name, :new_column_name
  end

3

Ruby on Rails geçişi oluşturun :

$:> rails g migration Fixcolumnname

Geçiş dosyasına kod ekleyin (XXXXXfixcolumnname.rb) :

class Fixcolumnname < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

2

Ruby on Rails konsolunuzu açın ve şunu girin:

ActiveRecord::Migration.rename_column :tablename, :old_column, :new_column

2

Bunu yapmanın iki yolu var:

  1. Bu tipte, geri alma sırasında otomatik olarak ters kodunu çalıştırır.

    def change
      rename_column :table_name, :old_column_name, :new_column_name
    end
  2. Bu türe, ne zaman yukarı yöntemini rake db:migrateçalıştırır ve ne zaman aşağı yöntemini çalıştırır rake db:rollback:

    def self.up
      rename_column :table_name, :old_column_name, :new_column_name
    end
    
    def self.down
      rename_column :table_name,:new_column_name,:old_column_name
    end

2

Ben raylar 5.2, ve bir tasarlanan Kullanıcı bir sütun yeniden adlandırmaya çalışıyorum.

rename_columnBiraz benim için çalıştı, ancak tekil :table_namebir attı hatası "Kullanıcı tablosunun bulunamadı". Çoğul benim için çalıştı.

rails g RenameAgentinUser

Ardından taşıma dosyasını şu şekilde değiştirin:

rename_column :users, :agent?, :agent

Nerede: ajan? eski sütun adıdır.


0

Güncelleme - create_table'ın yakın bir kuzeni change_table'dır ve mevcut tabloları değiştirmek için kullanılır. Create_table için benzer bir şekilde kullanılır, ancak bloğa verilen nesne daha fazla numara bilir. Örneğin:

class ChangeBadColumnNames < ActiveRecord::Migration
  def change
    change_table :your_table_name do |t|
      t.rename :old_column_name, :new_column_name
    end
  end
end

Bu şekilde aşağıdakiler gibi diğer değiştirme yöntemleri ile yaparsak daha verimli oluruz: indeksi kaldır / ekle / indeksi kaldır / sütun ekle, örneğin aşağıdakileri de yapabiliriz:

# Rename
t.rename :old_column_name, :new_column_name
# Add column
t.string :new_column
# Remove column
t.remove :removing_column
# Index column
t.index :indexing_column
#...

0

Sadece komutu kullanarak taşıma oluşturun

rails g migration rename_hased_password

Bundan sonra, taşıma yönteminde geçişi aşağıdaki satırı ekleyin

rename_column :table, :hased_password, :hashed_password

Bu hile yapmalı.


0

5 geçiş değişikliğini raylar

Örneğin:

rails g model Öğrenci student_name: string age: integer

öğrenci_adı sütununu ad olarak değiştirmek istiyorsanız

Not: - rayları çalıştırmazsanız db: migrate

Aşağıdaki adımları uygulayabilirsiniz

raylar d modeli Öğrenci öğrenci_adı: string age: integer

Bu oluşturulan taşıma dosyasını kaldıracak, Şimdi sütun adınızı düzeltebilirsiniz

rails g model Öğrenci adı: string age: integer

Taşındıysanız (raylar db: migrate), sütun adını değiştirmek için aşağıdaki seçenekler

rails g migration RemoveStudentNameFromStudent student_name: string

rails g geçiş AddNameToStudent name: string


Olmamalı mı: rails g migration RemoveStudentNameFromStudentS student_name:string(öğrenciler çoğuldur)?
BKSpurgeon

Ayrıca bu tehlikelidir: sütun yeniden adlandırılmaz, ancak tamamen kaldırılır ve sonra okunur. Verilere ne olacak? Kullanıcının isteyeceği şey bu olmayabilir.
BKSpurgeon
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.