2017-06-20 7 views
2

私は2つのカラム(Column_AとCOLUMN_B)既存のレコード(履歴データ)でレールの移行を行う方法は?

とモデル(Model_A)を持っている私のモデルは、その中に次のような方法があり、2は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の値を生成し、私は私がする必要があります知っています移行の最初のステップとして新しい列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

から、この移行のような

何かをSQLの方法を使用してすべてのレコードを更新することができますSQL自身でそれを行うことができる場合| x | x.save! } ' –

+0

ああ、それはもっと効率的だろう。この場合、 – Ucpuzz

1

すべてのレコードを超えるループは悪い考えです。 200万のレコードがあるとしましょう。ActiveRecordの方法では、列を更新してからコールバックと検証を実行することが永久に必要になります。

あなたはあなたが `ModelA.all.find_each {に変更したいかもしれませんシュプレー

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データ型ですか? –

関連する問題