Reputation: 1906
I have a table with five different has-many relationships to other tables. Before deleting a record, I need to move all of its children to another record. To accomplish this I employ the following code:
self.class.reflect_on_all_associations.select {|assoc| assoc.macro == :has_many }.each do |assoc|
target.send(assoc.name) << self.send(assoc.name)
end
Basically, this comes down to target.child-association << self.child-association
. But this does not work correctly, deleting all the children from "self" and adding a single child to "target" with all fields except the associated field null. I think this is because "<<" expects a record and I'm passing an array of records. I see that "<<" also accepts a list of arguments, so I think I need something like target.send(assoc.name) << *self.send(assoc. name)
(note the splat operator), but I can't figure out a valid syntax for doing this. So my questions are two:
Upvotes: 1
Views: 1034
Reputation: 1906
Ok, here are the answers:
1) target.send(assoc.name).send(:<<, *(self.send(assoc.name)))
2) The original technique is inefficient, generating 'n' SQL Updates, each one updating one child record. The more efficient technique is self.send(assoc.name).update_all(parent_id: target.id)
. It requires guilty knowledge of how the linking is accomplished (in my case and most cases, a single foreign key field) which I suppose could be reflected from the association).
Upvotes: 2