2009-06-09 8 views
16

Cela doit être quelque chose de simple mais ça me rend fou!
J'ai une migration où je veux mettre à jour un dossier aprèsRails ne me laisse pas changer d'enregistrement pendant la migration

class SubjectsTextField < ActiveRecord::Migration 
    def self.up 
    add_column :users, :subjects, :text 

    User.find(39).update_attribute :subjects, "hey there" 
    end 

    def self.down 
    remove_column :users, :subjects 
    end 
end 

La colonne est créée, mais quand je vais vérifier fiche 39, son domaine de sujets est nul et ne dit pas « Hé ». Aucune erreur n'est levée pendant la migration et la ligne update_attribute renvoie true comme si elle avait fonctionné.

Cette ligne fonctionne parfaitement dans la console et a l'effet escompté:

User.find(39).update_attribute :subjects, "hey there" 

J'ai essayé de mettre la ligne de update_attribute dans une deuxième migration. Si je les traverse tous les deux dans un "rake db: migrate" jusqu'au courant, ça ne marche toujours pas.

Mais voici la partie étrange. Si j'exécute deux migrations séparées, dites "rake db: migrate VERSION = 10" pour créer uniquement la colonne puis la seconde avec "rake db: migrate" pour mettre à jour l'attribut IT WORKS!

Que diable se passe-t-il ... comment modifier un enregistrement pendant une migration? Je me souviens de l'avoir fait assez souvent par le passé. Peut-être que c'est quelque chose de différent avec Rails 2.3.2?

Merci! Brian

Répondre

33

Vous devez appeler reset_column_information sur le modèle que vous avez changé avant de pouvoir utiliser la nouvelle colonne. Ajouter ce entre la add_column et mise à jour:

User.reset_column_information 

Voir « Utilisation d'un modèle après avoir changé sa table » sur la page ActiveRecord::Migration.

+0

c'était grâce à Michael! Je ne peux pas croire que je n'ai jamais rencontré ça avant ... merci mille fois. –

+0

J'ai eu un problème similaire. Quelqu'un n'a pas utilisé t.timestamps sur une migration qui a créé un modèle, mais a fait t.datetime: updated_at. Je voulais donc ajouter: created_at et initialiser tous les objets existants 'created_at à la valeur courante de updated_at, mais c'était toujours nul. La chose étrange était que cela a bien fonctionné quand j'ai essayé d'utiliser Time.now. Quoi qu'il en soit, merci Michael. Votre message a beaucoup aidé! Cela l'a arrangé pour moi. – bratsche

+0

Merci Michael pour le lien vers la page api: ça aide à rester à jour car sur d'autres pages j'ai trouvé que la méthode #reset_column_information est obsolète .. – Attilio

0

Si vous combinez les deux dans votre migration initiale comme ceci, cela fonctionne-t-il?

class SubjectsTextField < ActiveRecord::Migration 
    def self.up 
    add_column :users, :subjects, :text 

    User.find(39).update_attribute "subjects", "hey there" 
    end 

    def self.down 
    remove_column :users, :subjects 
    end 
end 
+0

Non ne fonctionne pas de cette façon avec les citations, merci pour la réponse! –

1

Cette syntaxe est beaucoup plus clair ... essayez avec change_table

class AddReceiveNewsletterToUsers < ActiveRecord::Migration 
    def self.up 
    change_table :users do |t| 
     add_column :users, :subjects, :text 
    end 
    User.find(39).update_attribute "subjects", "hey there" 
    end 

    def self.down 
    remove_column :users, :receive_newsletter 
    end 
end 
Questions connexes