Activerecord Rails:深度复制具有多态子项的记录

Activerecord Rails:深度复制具有多态子项的记录,activerecord,ruby-on-rails-4,Activerecord,Ruby On Rails 4,因此,我正在寻找和现有的数据库记录,并复制它。当我执行一个简单的.dup时,没有任何多态资产被复制 class Contact < ActiveRecord::Base belongs_to :user has_one :profile, as: :profileable, dependent: :destroy has_one :address, through: :profile has_many :phones, through: :profile has

因此,我正在寻找和现有的数据库记录,并复制它。当我执行一个简单的.dup时,没有任何多态资产被复制

class Contact < ActiveRecord::Base
  belongs_to :user
  has_one :profile, as: :profileable, dependent: :destroy
  has_one :address,   through: :profile
  has_many :phones,   through: :profile
  has_many :photos,   through: :profile
  has_many :emails,   through: :profile
  has_many :socials,  through: :profile
  has_many :websites, through: :profile
end

class Profile < ActiveRecord::Base
  belongs_to :profileable, polymorphic: true
  has_many :addresses, as: :addressable, dependent: :destroy
  has_many :phones, as: :phoneable, dependent: :destroy
  has_many :photos, as: :photable, dependent: :destroy
  has_many :emails, as: :emailable, dependent: :destroy
  has_many :socials, as: :sociable, dependent: :destroy
  has_many :websites, as: :websiteable, dependent: :destroy
end

是否成功将配置文件复制到ID为1的用户的新联系人中。但在本例中,地址、电话、照片、电子邮件、社交和网站信息不会复制过来。如果每个依赖子项存在,我如何复制它?

因为我没有得到回复;我通过一个小小的元编程编写了自己的:

def new_contact_from_existing_profile(user_id, profile_id)
  params = {}
  %w^Address Phone Photo Email Social Website^.each do |poly_child|
    prefix = eval(poly_child).reflect_on_all_associations(:belongs_to).first.name.to_s
    the_type = prefix + "_type"
    the_id = prefix + "_id"
    eval(poly_child).where(the_type.to_sym => "Profile").where(the_id.to_sym => profile_id).each.with_index do |x,i|
      if  params[ eval(poly_child).table_name + "_attributes" ].nil?
        params[ eval(poly_child).table_name + "_attributes" ] = {}
      end
      params[ eval(poly_child).table_name + "_attributes" ][i.to_s] = x.dup.attributes
    end
  end
  Contact.new(
    user_id: user_id,
    profile: Profile.new(
      Profile.find(profile_id).dup.attributes.update params
    )
  ).save
end
对于任何其他想要深度复制的人,我已经写了一个gem,可以帮你处理这个问题

def new_contact_from_existing_profile(user_id, profile_id)
  params = {}
  %w^Address Phone Photo Email Social Website^.each do |poly_child|
    prefix = eval(poly_child).reflect_on_all_associations(:belongs_to).first.name.to_s
    the_type = prefix + "_type"
    the_id = prefix + "_id"
    eval(poly_child).where(the_type.to_sym => "Profile").where(the_id.to_sym => profile_id).each.with_index do |x,i|
      if  params[ eval(poly_child).table_name + "_attributes" ].nil?
        params[ eval(poly_child).table_name + "_attributes" ] = {}
      end
      params[ eval(poly_child).table_name + "_attributes" ][i.to_s] = x.dup.attributes
    end
  end
  Contact.new(
    user_id: user_id,
    profile: Profile.new(
      Profile.find(profile_id).dup.attributes.update params
    )
  ).save
end