2009-07-29 5 views
6

Voici ma situation: J'ai 2 objets personne, person1 et person2, qui ont été créés à partir de deux sources de données externes différentes. J'ai un processus manuel que j'utilise qui a déterminé que personne1 et personne2 se réfèrent réellement à la même personne, donc ce que je veux faire est de les "fusionner" en une seule personne, et enlever le double. Je n'ai aucun problème à le faire champ par champ pour l'objet lui-même, mais la chose qui devient difficile, et qui sera difficile à maintenir si je le fais mal, c'est que ces personnes ont des associations (ne le font pas nous tous). Ce que je veux faire, c'est après avoir copié les champs appropriés dans person1 (que je vais utiliser à l'avenir), je veux aussi déplacer les associations de person2 à person1.Comment mieux "fusionner" deux objets et leurs associations dans des rails?

Je pense que ma question se résume à ceci: Y at-il un moyen de 1) itérer sur chaque association pour un objet, et 2) déterminer le champ foreign_key pour cette association. Je suis assez sûr que si j'étais capable de faire ces choses, je pourrais écrire une méthode qui déplace automatiquement chaque enregistrement associé de person2 à person1, et ne pas changer ce code si j'ajoute ou supprime une association.

Des idées sur comment faire cela?

Merci.

Editer: J'ai mis en œuvre (aussi rapidement et de manière aussi directe que possible, alors que cela semble fonctionner) du code basé sur les pointeurs donnés dans la réponse de Duncan. Au cas où cela aiderait quelqu'un, voici un aperçu de la façon dont vous pourriez déplacer tous les objets associés d'un objet (@ p2 dans ce cas) à un autre (@ p1).

Person.reflect_on_all_associations.each do |assoc| 
    if assoc.macro == :has_many 
    @p2.send(assoc.name).each do |assoc_obj| 
     assoc_obj.update_attribute(assoc.primary_key_name, @p1.id) 
    end 
    elsif assoc.macro == :has_one 
    @p2.send(assoc.name).update_attribute(assoc.primary_key_name, @p1.id) 
    end 
end 

Répondre

3

Pour inspecter les associations d'programatically un objet ActiveRecord vous souhaitez utiliser ActiveRecord::Reflection. Les méthodes de classe définies ici renvoient des collections composées de ActiveRecord::Reflection::AssociationReflection à partir de laquelle vous pouvez extraire la clé étrangère, la clé primaire, le nom de la table, etc ...

Questions connexes