32 votes

Peut-on utiliser Rails Migrations pour convertir des données?

J'essaie de convertir une colonne de mon application Rails. Supposons que, par souci d'argument, j'essaie de modifier la colonne age de ma table users en une représentation sous forme de chaîne plutôt qu'en int.

Dans ma migration, j'ai ceci;

 def.self up
    add_column :users, :age_text, :string

    users = User.find(:all)

    users.each do |u|
       u.age_text = convert_to_text(u.age)
       u.save
    end
end

def self.convert_to_text(number)
   #code here to convert 1 to 'one' etc
end
 

Mais cela ne semble pas fonctionner, est-ce que ce que je tente ici est même possible avec les migrations?

58voto

Eduardo Scoz Points 11820

Ce que vous essayez de faire est possible, et je dirais la bonne chose à faire.

Cependant, vous devez recharger les informations de colonne pour les classes de modèle que vous mettez à jour dans la migration, afin que Rails connaisse les nouvelles colonnes. Essaye ça:

 def.self up
    add_column :users, :age_text, :string

    User.reset_column_information 

    users = User.find(:all)

    users.each do |u|
       u.age_text = convert_to_text(u.age)
       u.save
    end
end
 

Sur une note séparée, veuillez noter que si votre table est grande, effectuer des mises à jour une par une prendra un temps considérable. Soyez prudent avec cela.

39voto

Brian Hogan Points 2268

Depuis que je suis nouveau ici, je ne peux pas commenter sur le dessus donc je vais ajouter ma propre réponse.

GÉNÉRALEMENT la manipulation de données sur les migrations est une MAUVAISE idée. Les Migrations direct avec le modèle de l'accès peut être bloqué si le modèle logique des changements.

Imaginez dans votre deuxième migration, vous avez ajouté une nouvelle colonne. Vous souhaitez graines de cette colonne avec de nouvelles données.

Disons aussi quelques semaines plus tard, vous ajoutez une nouvelle validation du modèle la validation qui fonctionne sur un champ qui n'existe pas encore dans votre deuxième migration. si vous ne l'ont jamais été de construire la base de données de migration de 0, tu as quelques problèmes.

Je suggère fortement à l'aide de migrations de modifier les colonnes et d'autres moyens pour gérer les données de base de données, en particulier lors du passage à la production.

4voto

Chloe Points 2737

Voici un exemple de migration que j'ai exécuté pour convertir des données. Vous pouvez facilement le convertir pour utiliser des entiers au lieu de chaînes. La conversion en SQL est beaucoup plus rapide que le chargement de chaque ligne dans Rails.

 class ConvertCommentTextToText < ActiveRecord::Migration
  def up
    add_column :comments, :text_tmp, :text
    # copy text column
    execute <<-SQL
      update comments set text_tmp = text
    SQL
    remove_column :comments, :text
    rename_column :comments, :text_tmp, :text
  end

  def down
    add_column :comments, :text_tmp, :string
    # copy text column
    execute <<-SQL
      update comments set text_tmp = text
    SQL
    remove_column :comments, :text
    rename_column :comments, :text_tmp, :text
  end

end
 

Et pour le tester:

 rake db:migrate
rake db:rollback
rake db:migrate
 

0voto

science Points 107

Je dirais que si vous pouvez "annuler" les données importées lors de la restauration de la migration de version, alors qu'il est approprié de mettre les importations dans la migration.

Par exemple, j'ai une migration qui met en place beaucoup de tables de recherche et d'autres méta-données. Les données de ces tables sont remplies au cours de cette phase. Comme les données de ces tables de changements, je vais créer de nouveaux fichiers YAML stocker les méta-données et de charger ces fichiers dans la suite des migrations (et non ceux YAMLS, re-chargement de la précédente fichier YAML lors de la sauvegarde d'une migration de version). C'est assez propre. J'ai des fichiers (dans plusieurs dossiers définis par dans mon cas) avec ces fichiers:

002_setup_meta_data.rb
002_meta_data.yaml


007_change_meta_data.rb
007_meta_data.yaml

Si vous êtes à l'importation de la "production" des données à partir d'un autre système transactionnel (non statique) tables, alors je dirais à l'aide des migrations n'est pas approprié. Alors je voudrais suivre Brian Hogan conseils de l'aide du râteau tâches.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X