2017-06-20 54 views
2

我有兩列(Column_A和Column_B)如何在現有記錄(歷史數據)上進行軌道遷移?

我的模式有以下方法中,兩個基於column_A

Class Model_A < ActiveRecord::Base 
    before_save :set_column_B 

    def set_column_B 
     self.column_B = get_value_from_column_A 
    end 

    def get_value_from_column_A 
    # manipulate data from A to get value 
    column_A.join(,) 
    end 

end 

我知道我必須column_B價值模型(Model_A)創建一個新的column_B作爲遷移的第一步,但是如何更改數據庫中所有預先存在的記錄以在column_B中具有正確的值? 我應該寫一個腳本或Rake任務到這個或有辦法,我可以通過遷移嗎?

回答

0

在你可以做以下遷移:

class AddColummBToModelA < ActiveRecord::Migration 
    def up 
    unless column_exists? :budgets, :column_b 
     add_column :budgets, :column_b ...... 
     ModelA.find_each {|x| x.save! } 
    end 

    end 

    def down 
    remove_column :budgets, :column_b if column_exists? :budgets, :column_b 
    end 
end 
+0

你可能想將其更改爲'ModelA.all.find_each {更新所有記錄| X | x.save! }' –

+0

哦,是的,那會更有效率。 – Ucpuzz

1

循環對所有記錄是一個糟糕的主意,如果你有很多在他們的記錄。假設您有200萬條記錄,如果您要採用ActiveRecord的方式,則需要永久更新該列,然後執行回調和驗證。

如果你可以用SQL本身做到這一點,你可以使用SQL的方式

事情是這樣的遷移從施普雷

class UpdateNameFieldsOnSpreeCreditCards < ActiveRecord::Migration 
    def up 
    if ActiveRecord::Base.connection.adapter_name.downcase.include? "mysql" 
     execute "UPDATE spree_credit_cards SET name = CONCAT(first_name, ' ', last_name)" 
    else 
     execute "UPDATE spree_credit_cards SET name = first_name || ' ' || last_name" 
    end 
    end 

    def down 
    execute "UPDATE spree_credit_cards SET name = NULL" 
    end 
end 
+0

在這種情況下,我不使用模型中的方法來生成值。這似乎更像是添加一個默認值? –

+0

你到底在做什麼?如果它是像串接,乘法,加法或者我們可以使用SQL實現的東西,那麼你可以使用原始更新全部 –

+0

是你的columnA Array數據類型嗎? –