提问人:CafeHey 提问时间:5/12/2011 最后编辑:benzadoCafeHey 更新时间:11/27/2018 访问量:30582
在 rails 中克隆记录,是否可以克隆关联和深度复制?
Cloning a record in rails, is it possible to clone associations and deep copy?
问:
我正在 .clone -ing rails 中的记录......
new_blerg = Blerg.find(1).clone
此记录具有大量关联,这些关联甚至具有关联。
有没有办法深度复制记录并克隆它,以便它也与所有这些关联一起克隆?
答:
您需要编写自己的 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
您可能会很好地利用 ActiveRecord 3.2 的 Amoeba gem。
它支持简单和自动的递归复制、关联、字段预处理和高度灵活和强大的配置 DSL,既可以应用于模型,也可以动态应用。has_one
has_many
has_and_belongs_to_many
请务必查看 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
这些不同的选项中的每一个都应该导致使用与旧帖子相同的标签重新关联新帖子,但不会重复评论。
如果您启用它们,阿米巴也会自动递归到子记录中
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
除了预置之外,您还可以在给定字段上追加或运行正则表达式
享受!:)
评论
ActiveRecord::Base#dup
amoeba_dup
同样,这个宝石似乎工作得很好:https://github.com/moiristo/deep_cloneable,而且非常易于使用。
只
gem ‘deep_cloneable’, ‘~> 1.4.0’
然后:
pirate.deep_clone :include => :mateys
评论
amoeba
评论