带有过滤嵌套元素的Ruby on rails clone / dup

时间:2017-03-23 17:57:14

标签: ruby-on-rails ruby

我在尝试克隆具有嵌套元素的对象时遇到问题。我知道如何完全克隆它,但我想在每个嵌套级别只克隆一些子元素。

所以,假设我有这样的结构,我通过示例名称制作(不是实际情况)

class Town < ActiveRecord::Base
 has_many :districts
 has_many :buildings, through: :districts

class District < ActiveRecord::Base
 belongs_to :town
 has_many :buildings

class Building < ActiveRecord::Base
 belongs_to :district
 has_many :rooms
 has_many :toilets

 #and i have of course rooms and toilets with belongs_to relation to Building

所以如果我想克隆整个现有的Town对象,我会做类似的事情

Town.last.clone

但我想做这样的事情。我想复制现有的Town,然后根据我拥有的集合重新创建一些子对象。因此,如果城镇有10个区,我想只复制其中一个,或者更多(根据我的收藏),然后区有100个房子,我将再次复制我需要的那些等等直到房间和洗手间。所以我试着用这样的东西。

#now i have these collections, i get them in some fashion, and they belong to Town(1) below    
districts = District.find(1,2,3) #those ids are belonging to Town
buildings = Building.find(1,2,3) #those ids are belonging to districts above
rooms = Room.find(1,2,3,4,5,6) # and are belonging to some of buildings above
toilets = Toilet.find(1,2,3,4,5,6,7) #and are belonging to some of buildings

#so now i want to do this
old_town = Town.find(1)
new_town = old_town.dup.tap

districts.each od |district|
  new_town.districts << district.dup
end
#and i get all the districts to new created town but when i try further in nesting it wont work, like this

districts.each od |district|
  new_town.districts << district.dup

  buildings.each do |building|
    district.buildings << building.dup
  end
end

#and so on inside it for toilets and rooms it just wont work, like it doesnt attach them to new_town. What am i doing wrong?

所以我只想要选择性复制/克隆属于父级的过滤元素。彼此尊重他们的关系。

感谢分配。

1 个答案:

答案 0 :(得分:0)

districts.each do |district|
  district_dup = district.dup
  buildings.each do |building|
    district_dup.buildings << building.dup
  end
  new_town.districts << district_dup
end
你可以试试这样的吗?如果您想添加房间和厕所,则需要像building_dup一样创建district_dup

编辑:清洁版

districts.map(&:dup).each do |dis| #creates an Array of duplications and iterates through elements
  dis.buildings = buildings.map(&:dup).each do |building| #creates an Array of duplications which is later added to dis.buildings
    building.rooms = rooms.map(&:dup)
    building.toilets = toilet.map(&:dup)
  end
end

如果dis.buildings = buildings.map(&:dup).each失败,请尝试在所有情况下将#=更改为#concat