2015-09-30 26 views
7

alanlarını integer'a dönüştürmem gerekiyor ve bunun yerine enum kullanın. Verileri kaybetmeden bunu yapmanın en iyi yolu nedir?Sütunlar veri türünü tamsayı ve geri veri koruyarak (postgres) dize arasında geçiş yapmak için 4 geçişi Geçiş

Bu, geçerli taşıma geçerli:

class ChangeColumnsForSystems < ActiveRecord::Migration 
    def change 
    change_column :systems, :operation, :integer 
    change_column :systems, :status, :integer 
    end 
end 

Ve güncelleme model dosyası:

class CreateSystems < ActiveRecord::Migration 
    def change 
    create_table :systems do |t| 
     t.string :operation 
     t.string :status 

     t.timestamps null: false 
    end 
    end 
end 

Sonra ben gibi alanlarda türünü değiştirmek.

/app/models/system.rb eski verileri güncelleyebilir nasıl

... 
enum operation { start: 0, stop: 1 } 
enum status { init: 0, working: 1, complete: 2 } 
... 

? Sen 2 göçün yapabiliriz

cevap

7

Bazı araştırmalardan sonra bunun uygun bir çözüm olduğunu keşfettim.

class ChangeColumnsForSystems < ActiveRecord::Migration 
    def change 
    change_column :systems, :operation, "integer USING (CASE operation WHEN 'start' THEN '0'::integer ELSE '1'::integer END)", null: false 
    change_column :systems, :status, "integer USING (CASE status WHEN 'init' THEN '0'::integer WHEN 'working' THEN '1'::integer ELSE '2'::integer END)", null: false 
    end 
end 

GÜNCELLEME: Eğer tipini değiştirerek önce varsayılan değeri kaldırmak zorunda kalacak Bazı durumlarda . İşte geri alma ile sürümü.

class ChangeColumnsForSystems < ActiveRecord::Migration 
    def up 
    change_column_default :systems, :status, nil 
    change_column :systems, :operation, "integer USING (CASE operation WHEN 'start' THEN '0'::integer ELSE '1'::integer END)", null: false 
    change_column :systems, :status, "integer USING (CASE status WHEN 'init' THEN '0'::integer WHEN 'working' THEN '1'::integer ELSE '2'::integer END)", null: false, default: 0 
    end 

    def down 
    change_column_default :systems, :status, nil 
    change_column :systems, :operation, "varchar USING (CASE operation WHEN '0' THEN 'start'::varchar ELSE 'stop'::varchar END)", null: false 
    change_column :systems, :status, "varchar USING (CASE status WHEN '0' THEN 'init'::varchar WHEN '1' THEN 'working'::varchar ELSE 'complete'::varchar END)", null: false, default: 'init' 
    end 
end 
2

1. akım operation sütunu yeniden adlandırma ve eskiden yeniye sütundan gerekli tip

def up 
    rename_column :systems, :operation, :operation_str 
    add_column :systems, :operation, ... # your options 
end 

2. Taşı değerlerini yeni ekleyebilir ve eski sütun bırakın adımları

def up 
    System.all.each do |sys| 
     sys.operation = sys.operation_str.to_i # replace it with your converter 
    end 
    remove_column :systems, :operation 
end 

o gerekli olmadığını yazma geri alma kodu unutma

+0

Bu göç bozuk tüm veriler, bir ipe '.to_i' çağırdığınızda çünkü, her zaman beklendiği gibi kod 0. Sonraki parça çalışacak alacak olacaktır. Ancak bu en iyi çözüm değil 'sys.operation = System.operations [sys.operation_str]' – Pav31