我正在Rails中使用.clone复制一条记录...
new_blerg = Blerg.find(1).clone
这条记录有大量的关联,并且这些关联还有它们自己的关联。
有没有一种方法可以深度复制记录并克隆它,使它被克隆时所有这些关联也被克隆?
我正在Rails中使用.clone复制一条记录...
new_blerg = Blerg.find(1).clone
这条记录有大量的关联,并且这些关联还有它们自己的关联。
有没有一种方法可以深度复制记录并克隆它,使它被克隆时所有这些关联也被克隆?
has_one
、has_many
和has_and_belongs_to_many
关联的易于递归复制、字段预处理以及高度灵活和强大的配置DSL(可应用于模型和即时应用)。请务必查看Amoeba文档,但使用方法非常简单...只需gem install amoeba
或者添加
gem 'amoeba'
将其添加到Gemfile中
然后在你的模型中添加amoeba块,并像平常一样运行dup
方法。
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
enable
end
end
class Comment < ActiveRecord::Base
belongs_to :post
end
class Tag < ActiveRecord::Base
has_and_belongs_to_many :posts
end
class PostsController < ActionController
def some_method
my_post = Post.find(params[:id])
new_post = my_post.dup
new_post.save
end
end
你的新帖子应该具有最初与其关联的所有标签,所有评论也应当被复制。您可以通过DSL禁用各种记录的复制,有关此内容的详细信息请参阅文档,但例如,如果您想保留标签,但不想保留评论,则可以执行以下操作:
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
include_field :comments
end
end
或者使用独家语法
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
exclude_field :comments
end
end
或者通过指定要识别的字段类型(并因此复制)
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
recognize :has_and_belongs_to_many
end
end
这些不同的选项中,每个选项都应该会将新帖子重新关联到与旧帖子相同的标签,但不会复制评论。
如果启用了子记录,Amoeba还将自动递归进入子记录。
class Post < ActiveRecord::Base
has_many :comments
amoeba do
enable
end
end
class Comment < ActiveRecord::Base
belongs_to :post
has_many :ratings
amoeba do
enable
end
end
class Rating < ActiveRecord::Base
belongs_to :comment
end
您还可以在字段前缀上添加一些额外的数据以指示唯一性
class Post < ActiveRecord::Base
has_many :comments
amoeba do
enable
prepend :title => "Copy of "
end
end
除了可以使用prepend,你还可以将内容附加到给定字段的末尾,或者对其运行正则表达式。
祝使用愉快!:)
ActiveRecord :: Base#dup
方法,而是实现了自己的方法称为amoeba_dup
...” - Sam您需要编写自己的clone_with_associations方法,该方法通过指定的一组关联进行遍历。理论上,您可以编写一个使用reflect_on_all_associations的通用方法,但您需要在关联对象上执行相同的操作,这最终会创建一个生成无限记录的循环。
因此,只需编写自己的方法。类似于以下内容:
#in Blerg
has_many :foos
has_many :bars #bars also have many chickens which we want to copy over as well
def clone_with_associations
new_blerg = self.dup
new_blerg.save
#simple association
new_blerg.foos = self.foos
#two-level association
self.bars.each do |bar|
new_bar = bar.clone
new_bar.save
new_bar.chickens = bar.chickens
new_blerg.bars << bar
end
new_blerg
end
现在你可以这样做
@new_blerg = Blerg.find(1).clone_with_associations
new_blerg.foos = self.foos
时,你将得到一个损坏的原始对象,因为它窃取了你的关联。你需要同时克隆它们。 - RocketRdef duplicate_records new_course = self.deep_clone new_course.image = File.open(self.image.file.file) if self.image.present? new_course.save new_course.chapters = self.chapters new_course.chapters.each do |chapter| new_chapter = chapter.clone new_chapter.image = File.open(chapter.image.file.file) if chapter.image.present? new_chapter.save end new_course end
- LearningRORnew_course.chapters.each do |chapter|
替换为 self.chapters.each do |chapter|
。请记住,self
是被克隆的对象。 - Max Williams只需执行:
gem ‘deep_cloneable’, ‘~> 1.4.0’
然后:
pirate.deep_clone :include => :mateys