Ruby-on-rails 在rails中克隆记录,是否可以克隆关联和深拷贝?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5976684/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:07:12  来源:igfitidea点击:

Cloning a record in rails, is it possible to clone associations and deep copy?

ruby-on-railsactiverecordduplicatesclonedeep-copy

提问by MintDeparture

I'm .clone -ing a record in rails...

我是 .clone - 在 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?

有没有办法深度复制记录并克隆它,以便它也与所有这些关联一起克隆?

采纳答案by Vaughn Draughon

You may get some good use out of the Amoeba gemfor ActiveRecord 3.2.

您可能会很好地利用ActiveRecord 3.2的Amoeba gem

It supports easy and automatic recursive duplication of has_one, has_manyand has_and_belongs_to_manyassociations, field preprocessing and a highly flexible and powerful configuration DSL that can be applied both to the model and on the fly.

它支持的简单和自动递归重复has_onehas_manyhas_and_belongs_to_many协会,现场预处理和既能对模型和动态应用了灵活而强大的配置DSL。

be sure to check out the Amoeba Documentationbut 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 dupmethod 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

如果您启用它们,变形虫还会自动递归到子记录

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! :)

享受!:)

回答by Max Williams

You'd need to write your own clone_with_associations method which goes through a specific listed set of associations. Theoretically you couldwrite 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

回答by Rob

Equally, this gem seems to work well: https://github.com/mtheitroadisto/deep_cloneable, and is pretty easy to use.

同样,这个 gem 似乎运行良好:https: //github.com/mtheitroadisto/deep_cloneable,并且非常易于使用。

Just

只是

gem ‘deep_cloneable', ‘~> 1.4.0'

gem ‘deep_cloneable', ‘~> 1.4.0'

and then:

进而:

pirate.deep_clone :include => :mateys

pirate.deep_clone :include => :mateys