Değişiklik sütunu için ray taşıma


327

script/generate migration add_fieldname_to_tablename fieldname:datatypeBir modele yeni sütunlar eklemek için sözdizimimiz var .

Aynı satırda, bir sütunun veri türünü değiştirmek için bir komut dosyanız / oluşturmamız var mı? Yoksa doğrudan vanilya taşıma işlemime SQL yazmalı mıyım?

Ben bir sütun değiştirmek istediğiniz datetimeiçin date.

Yanıtlar:


548

Bunun işe yarayacağını düşünüyorum.

change_column :table_name, :column_name, :date

13
@b_ayan: bildiğim kadarıyla, taşıma adlarındaki tek sihirli kelime "ekle" ve "kaldır".
Alex Korban

1
Burada bir çeşit ray var, ama… Cevabı anlıyorum ama bu cevabın yorumlarını bilmiyorum. Açıklamalar takdir :)
Alan H.

7
Bir taşıma oluşturduğunuzda, ona bir ad verirsiniz (örn. Yukarıdaki soruda add_fieldname_to_tablename). "Ekle" veya "kaldır" ile başlarsa, sütun eklemek veya kaldırmak için taşıma işlemi otomatik olarak kodla doldurulur ve bu da bu kodu kendiniz yazmanızı sağlar.
Alex Korban

6
Geri dönüşü olmayan bir göç olduğu gibi , normal changeeylemi ayrı upve downeylemlerle değiştirmeniz gerektiğini ve change_columngeri almanız gerektiğinde bir hata oluşturacağını da akılda tutmak gerekir.
DaveStephens

1
@QPaysTaxes, sütununuzu çift yönlü olarak değiştirmek istediğinizi içermeli ve aşağı, bu değişikliğin nasıl geri alınacağını içermelidir.
DaveStephens

98

Bir tablo içinde değiştirmek için birden çok sütununuz varsa bir blok da kullanabilirsiniz.

Misal:

change_table :table_name do |t|
  t.change :column_name, :column_type, {options}
end

Daha fazla bilgi için Table sınıfındaki API belgelerine bakın.


88

Tüm bunları yapmak için komut satırından bir geçiş oluşturabileceğinizi bilmiyorum, ancak yeni bir geçiş oluşturabilir, ardından bu görevleri gerçekleştirmek için geçişi düzenleyebilirsiniz.

Tablename tablonuzun adı ise, fieldname alanınızın adıysa ve datetime'dan bugüne değiştirmek istiyorsanız, bunu yapmak için bir geçiş yazabilirsiniz.

Şunlarla yeni bir taşıma oluşturabilirsiniz:

rails g migration change_data_type_for_fieldname

Ardından change_table öğesini kullanmak için taşımayı düzenleyin:

class ChangeDataTypeForFieldname < ActiveRecord::Migration
  def self.up
    change_table :tablename do |t|
      t.change :fieldname, :date
    end
  end
  def self.down
    change_table :tablename do |t|
      t.change :fieldname, :datetime
    end
  end
end

Ardından taşıma işlemini çalıştırın:

rake db:migrate

32

Önceki cevaplarda bulduğum gibi, bir sütunun türünü değiştirmek için üç adım gereklidir:

Aşama 1:

Bu kodu kullanarak yeni bir taşıma dosyası oluşturun:

rails g migration sample_name_change_column_type

Adım 2:

/db/migrateKlasöre gidin ve yaptığınız taşıma dosyasını düzenleyin. İki farklı çözüm var.

  1. def change
        change_column(:table_name, :column_name, :new_type)
    end

2.

    def up
        change_column :table_name, :column_name, :new_type
    end

    def down
        change_column :table_name, :column_name, :old_type
    end

Aşama 3:

Bu komutu yapmayı unutmayın:

rake db:migrate

Bu çözümü Rails 4 için test ettim ve iyi çalışıyor.


1
Adım 2'de, ilk komisyon db: rollback çalıştırdıktan sonra başarısız olacaktır, ikincisini kontrol etmenizi öneririz
Feuda

Geçiş dosyasını oluşturmadan ve daha sonra düzenlemeden oluştururken her şeyin az çok yapılmasına izin veren bir raylar kuralı var mı?
BKSpurgeon

@BKSpurgeon Evet, buradaki belgelere bakın: edgeguides.rubyonrails.org/active_record_migrations.html
Aboozar Rajabi

12

Raylı 5

Gönderen Raylar Kılavuzları :

Bir taşıma işleminin Aktif Kayıt'ın nasıl tersine çevireceğini bilmediği bir şey yapmasını istiyorsanız, aşağıdakileri kullanabilirsiniz reversible:

class ChangeTablenameFieldname < ActiveRecord::Migration[5.1]
  def change
    reversible do |dir|
      change_table :tablename do |t|
        dir.up   { t.change :fieldname, :date }
        dir.down { t.change :fieldname, :datetime }
      end
    end
  end
end

8

Sadece taşıma oluşturun:

rails g migration change_column_to_new_from_table_name

Taşıma işlemini şu şekilde güncelleyin:

class ClassName < ActiveRecord::Migration
  change_table :table_name do |table|
    table.change :column_name, :data_type
  end
end

ve sonunda

rake db:migrate

2

Taşıma işlemini kullanarak veri türünü değiştirmenin başka bir yolu

Adım 1: Taşıma kullanarak hatalı veri türü alan adını kaldırmanız gerekir

örn:

rails g migration RemoveFieldNameFromTableName field_name:data_type

Burada alanınız için veri türü belirtmeyi unutmayın

2. Adım: Artık doğru veri türüne sahip alan ekleyebilirsiniz

örn:

rails g migration AddFieldNameToTableName field_name:data_type

İşte bu, şimdi tablonuz doğru veri türü alanı, Happy ruby ​​kodlaması ile eklenecek!


2

Tüm bunlar, sütunun veri türünün mevcut veriler için örtük bir dönüşüme sahip olduğunu varsayar. Var olan verilerin, diyelim ki, a Stringdolaylı olarak yeni veri tipine dönüştürülebileceği çeşitli durumlarla karşılaştım Date.

Bu durumda, veri dönüşümleriyle taşıma oluşturabileceğinizi bilmek faydalıdır. Şahsen, bunları model dosyama koymayı ve sonra tüm veritabanı şemaları taşındıktan ve kararlı olduktan sonra bunları kaldırmayı seviyorum.

/app/models/table.rb
  ...
  def string_to_date
    update(new_date_field: date_field.to_date)
  end

  def date_to_string
    update(old_date_field: date_field.to_s)
  end
  ...
    def up
        # Add column to store converted data
        add_column :table_name, :new_date_field, :date
        # Update the all resources
        Table.all.each(&:string_to_date)
        # Remove old column
        remove_column :table_name, :date_field
        # Rename new column
        rename_column :table_name, :new_date_field, :date_field
    end

    # Reversed steps does allow for migration rollback
    def down
        add_column :table_name, :old_date_field, :string
        Table.all.each(&:date_to_string)
        remove_column :table_name, :date_field
        rename_column :table_name, :old_date_field, :date_field
    end

0

Varsayılan değerin düzenlenmesi durumunda cevapları tamamlamak için :

Ray konsolunuzda:

rails g migration MigrationName

Göçte:

  def change
    change_column :tables, :field_name, :field_type, default: value
  end

Gibi görünecek :

  def change
    change_column :members, :approved, :boolean, default: true
  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.