How best to “merge” two objects and their associat

2020-07-10 08:38发布

问题:

Here's my situation: I have 2 person objects, person1 and person2, which were created from two different external data sources. I have a manual process that I use that has determined that person1 and person2 actually refer to the same person, so what I want to do is "merge" them into a single person, and remove the duplicate.

I have no problem doing this on a field by field basis for the object itself, but the thing that gets tricky, and will be hard to maintain if I do it badly, is that these people have associations (don't we all). What I want to do is after copying the appropriate fields into person1 (which I'll use going forward), I want to move the associations from person2 to person1 as well.

I think my question boils down to this: Is there a way to 1) iterate over each association for an object, and 2) determine the foreign_key field for that association. I'm pretty sure that if I were able to do those things I could write a method that automatically moved each associated record from person2 to person1, and not change that code if I add or remove an association.

Any ideas on how to do this?

Thanks.

Edit: I've implemented (as quickly and dirtily as possible while it seems to work) code based on the pointers given in Duncan's answer. Just in case this helps anyone, this is a rough outline of how you could move all the associated objects from one objects (@p2 in this case) to another (@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

回答1:

To programatically inspect an ActiveRecord object's associations you'll want to use ActiveRecord::Reflection. The class methods defined here return collections comprised of ActiveRecord::Reflection::AssociationReflection from which you can extract the foreign key, primary key, table name, etc...