2017-06-20 3 views
2

J'ai un modèle (Model_A) avec deux colonnes (column_a et Column_B)Comment faire des migrations de rails sur des enregistrements existants (données historiques)?

Mon modèle a la méthode suivante en elle, deux générer de la valeur de column_B basée sur 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 

Je sais que je dois Créez une nouvelle colonne_B comme première étape de la migration. Cependant, comment puis-je modifier tous les enregistrements préexistants dans la base de données pour avoir la valeur correcte dans column_B? Dois-je écrire un script ou une tâche Rake ou y a-t-il un moyen de le faire via les migrations?

Répondre

0

Dans la migration, vous pouvez effectuer les opérations suivantes:

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

Vous voudrez peut-être changer à 'ModelA.all.find_each {| x | x.save! } ' –

+0

oh oui, ce serait plus efficace. – Ucpuzz

1

Looping sur tous les dossiers est une mauvaise idée si vous avez beaucoup de dossiers en eux. Supposons que vous ayez 2 millions d'enregistrements. Il faudra une éternité pour mettre à jour la colonne et ensuite exécuter les rappels et les validations si vous allez ActiveRecord.

Si vous pouvez le faire avec SQL lui-même, vous pouvez mettre à jour tous les enregistrements en utilisant SQL façon

Quelque chose comme cette migration de Spree

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

dans ce cas, je n'utilise pas la méthode dans le modèle pour générer la valeur. Cela semble plus comme ajouter une valeur par défaut? –

+0

Que faites-vous exactement dans cette méthode? Si c'est comme la concaténation, la multiplication, l'addition ou quelque chose que nous pouvons réaliser en utilisant le SQL, vous pouvez utiliser la mise à jour brute tous –

+0

Est-ce que votre type de données columnA Array? –