I want to merge two profiles into one. What is the best way to do this in Rails.
I have two profiles say user1
and user2
and there are at least 30 tables associated with them.
Now i want to merge them together so that there should be one profile say user1
and user2
should get deleted but all the associated data of user2
now should associate with user1
.
For example: suppose user2
has two contacts and user1
has 3 contacts after merging user user1
should have 5 contacts.
Something like this
@user1 = User.find(1);
@user2 = User.find(2);
Contact.where("user_id = ?", @user2.id).update_all(:user_id => @user1.id)
@user2.destroy
in case of generalize solution place file /lib/acts_as_user_merge.rb
module UserMerge
module ActsAsUserMerge
module Base
def self.included(klass)
klass.class_eval do
extend Config
end
end
end
module Config
def acts_as_user_merge
include ::UserMerge::ActsAsUserMerge::InstanceMethods
end
end
module InstanceMethods
def merge(user)
models = Array.new
models_names = User.reflections.collect{|a, b| b.class_name if b.macro==:has_many}.compact
models_names.each do |name|
models << Object.const_get name
end
models.each do |model|
model.where("user_id = ?", user.id).update_all(:user_id => self.id)
end
user.destroy
end
end
end
end
::ActiveRecord::Base.send :include, ::UserMerge::ActsAsUserMerge::Base
how to use
User < ActiveRecord::Base
has_many ...
acts_as_user_merge
end
@user1.merge(@user2)
kinda messy and not tested but should give you an idea
Something like that
def merge_users(dead, user)
User.reflections.each do |assoc, reflection|
foreign_key = reflection.foreign_key
case reflection.macro
when :has_many, :has_one then
unless reflection.options[:through]
reflection.klass.where(foreign_key => dead.id).update_all(foreign_key => user.id) # if id is a primary key
end
if options[:as] # polymorphic
if reflection.macro == :has_many
dead.send("#{options[:as].pluralize}")).each { |r| user.send("#{options[:as].pluralize}<<", r) }
else
user.send("#{options[:as]}=", dead.send("#{options[:as]}"))
user.save
end
end
when :belongs_to then
if options[:polymorphic]
user.send("#{assoc}=", deaf.send(assoc))
user.save
else
user.update_attribute(foreign_key, dead.send(foreign_key))
end
when :has_and_belongs_to_many then
dead.send("#{assoc}")).each { |r| user.send("#{assoc}<<", r) }
end
end
end
merge_users(dead_user, user)
dead_user.destroy
This article discusses this matter in depth, and provides the working code for it: http://ewout.name/2010/04/generic-deep-merge-for-activerecord/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With