I'm .clone -ing a record in rails...
我是。在铁路上抓住一条记录......
new_blerg = Blerg.find(1).clone
This record has loads and loads of associations, and those associations even have associations.
此记录具有负载和负载的关联,并且这些关联甚至具有关联。
Is there a way to deep-copy a record and clone it so it is cloned with all of those associations too?
有没有办法深度复制记录并克隆它,以便克隆所有这些关联呢?
3 个解决方案
#1
24
You may get some good use out of the Amoeba gem for ActiveRecord 3.2.
对于ActiveRecord 3.2,您可以从Amoeba gem中获得一些好处。
It supports easy and automatic recursive duplication of has_one
, has_many
and has_and_belongs_to_many
associations, field preprocessing and a highly flexible and powerful configuration DSL that can be applied both to the model and on the fly.
它支持has_one,has_many和has_and_belongs_to_many关联的简单和自动递归复制,字段预处理以及可以同时应用于模型和动态的高度灵活且功能强大的配置DSL。
be sure to check out the Amoeba Documentation but usage is pretty easy...
请务必查看Amoeba文档,但使用非常简单......
just
只是
gem install amoeba
or add
或添加
gem 'amoeba'
to your Gemfile
到您的Gemfile
then add the amoeba block to your model and run the dup
method as usual
然后将变形虫块添加到模型中并像往常一样运行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
Your new post should have all the tags that were originally associated with it, and all the comments should be duplicated as well. You can disable the duplication of various records through the DSL, which you can read about in the documentation, but for example, if you wanted to keep the tags, but not the comments you could do something like this:
您的新帖子应该包含最初与之关联的所有标记,并且所有评论也应该重复。您可以通过DSL禁用各种记录的复制,您可以在文档中阅读这些记录,但是,例如,如果您想保留标记,而不是注释,则可以执行以下操作:
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
include_field :comments
end
end
or using the exclusive syntax
或使用独家语法
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
exclude_field :comments
end
end
or by specifying which field types to recognize (and thusly copy)
或者通过指定要识别的字段类型(从而复制)
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
recognize :has_and_belongs_to_many
end
end
each of these various options should result in re-associating the new post with the same tags as the old post, but without duplicating the comments.
这些不同选项中的每一个都应该导致重新关联新帖子与旧帖子相同的标签,但不会重复评论。
Amoeba will also automatically recurse in to child records if you enable them
如果启用,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
You can also prefix fields with some extra data to indicate uniqueness
您还可以在字段前添加一些额外数据以指示唯一性
class Post < ActiveRecord::Base
has_many :comments
amoeba do
enable
prepend :title => "Copy of "
end
end
and in addition to prepend you can also append to or run a regex on a given field
除了前置之外,您还可以在给定字段上附加或运行正则表达式
Enjoy! :)
请享用! :)
#2
18
You'd need to write your own clone_with_associations method which goes through a specific listed set of associations. Theoretically you could write something generic which uses reflect_on_all_associations but you would need to do the same on the associated objects, and this would inevitably end up creating a loop that generates an infinite amount of records.
您需要编写自己的clone_with_associations方法,该方法通过特定列出的关联集。从理论上讲,你可以编写一些使用reflect_on_all_associations的泛型,但你需要在关联的对象上做同样的事情,这将不可避免地最终创建一个生成无限量记录的循环。
So, just write your own. Something like
所以,只需编写自己的。就像是
#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
Now you can do
现在你可以做到
@new_blerg = Blerg.find(1).clone_with_associations
#3
15
Equally, this gem seems to work well: https://github.com/moiristo/deep_cloneable, and is pretty easy to use.
同样,这个宝石似乎运作良好:https://github.com/moiristo/deep_cloneable,并且非常容易使用。
Just
只是
gem ‘deep_cloneable’, ‘~> 1.4.0’
宝石'deep_cloneable','〜> 1.4.0'
and then:
接着:
pirate.deep_clone :include => :mateys
pirate.deep_clone:include =>:mateys
#1
24
You may get some good use out of the Amoeba gem for ActiveRecord 3.2.
对于ActiveRecord 3.2,您可以从Amoeba gem中获得一些好处。
It supports easy and automatic recursive duplication of has_one
, has_many
and has_and_belongs_to_many
associations, field preprocessing and a highly flexible and powerful configuration DSL that can be applied both to the model and on the fly.
它支持has_one,has_many和has_and_belongs_to_many关联的简单和自动递归复制,字段预处理以及可以同时应用于模型和动态的高度灵活且功能强大的配置DSL。
be sure to check out the Amoeba Documentation but usage is pretty easy...
请务必查看Amoeba文档,但使用非常简单......
just
只是
gem install amoeba
or add
或添加
gem 'amoeba'
to your Gemfile
到您的Gemfile
then add the amoeba block to your model and run the dup
method as usual
然后将变形虫块添加到模型中并像往常一样运行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
Your new post should have all the tags that were originally associated with it, and all the comments should be duplicated as well. You can disable the duplication of various records through the DSL, which you can read about in the documentation, but for example, if you wanted to keep the tags, but not the comments you could do something like this:
您的新帖子应该包含最初与之关联的所有标记,并且所有评论也应该重复。您可以通过DSL禁用各种记录的复制,您可以在文档中阅读这些记录,但是,例如,如果您想保留标记,而不是注释,则可以执行以下操作:
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
include_field :comments
end
end
or using the exclusive syntax
或使用独家语法
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
exclude_field :comments
end
end
or by specifying which field types to recognize (and thusly copy)
或者通过指定要识别的字段类型(从而复制)
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
recognize :has_and_belongs_to_many
end
end
each of these various options should result in re-associating the new post with the same tags as the old post, but without duplicating the comments.
这些不同选项中的每一个都应该导致重新关联新帖子与旧帖子相同的标签,但不会重复评论。
Amoeba will also automatically recurse in to child records if you enable them
如果启用,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
You can also prefix fields with some extra data to indicate uniqueness
您还可以在字段前添加一些额外数据以指示唯一性
class Post < ActiveRecord::Base
has_many :comments
amoeba do
enable
prepend :title => "Copy of "
end
end
and in addition to prepend you can also append to or run a regex on a given field
除了前置之外,您还可以在给定字段上附加或运行正则表达式
Enjoy! :)
请享用! :)
#2
18
You'd need to write your own clone_with_associations method which goes through a specific listed set of associations. Theoretically you could write something generic which uses reflect_on_all_associations but you would need to do the same on the associated objects, and this would inevitably end up creating a loop that generates an infinite amount of records.
您需要编写自己的clone_with_associations方法,该方法通过特定列出的关联集。从理论上讲,你可以编写一些使用reflect_on_all_associations的泛型,但你需要在关联的对象上做同样的事情,这将不可避免地最终创建一个生成无限量记录的循环。
So, just write your own. Something like
所以,只需编写自己的。就像是
#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
Now you can do
现在你可以做到
@new_blerg = Blerg.find(1).clone_with_associations
#3
15
Equally, this gem seems to work well: https://github.com/moiristo/deep_cloneable, and is pretty easy to use.
同样,这个宝石似乎运作良好:https://github.com/moiristo/deep_cloneable,并且非常容易使用。
Just
只是
gem ‘deep_cloneable’, ‘~> 1.4.0’
宝石'deep_cloneable','〜> 1.4.0'
and then:
接着:
pirate.deep_clone :include => :mateys
pirate.deep_clone:include =>:mateys