Ruby on Rails 对象及其属性的深度复制/深度克隆

发布于 2024-11-15 23:26:29 字数 866 浏览 3 评论 0原文

我想对对象进行深度复制,包括所有属性。

Experiment_old 有 10 次试验。我想将 10 次试验的所有内容复制到experiment_new。 Experiment_old 还应保留 10 次试用信息。

然而,我在下面尝试的所有案例,它们都很好地复制了所有内容,但experiment_old没有10次试验的信息。他们只是出现在experiment_new上。

对于这些情况进行深复制的最佳方法是什么?

情况 1:

@experiment_new = Experiment.create(@experiment_old.attributes.merge(:trials => experiment_old.trails))

情况 2:

@experiment_new = Marshal.load(Marshal.dump(@experiment_old.trials))

情况 3:

@experiment_new = @experiment_old.clone

这是模型:

class Experiment < ActiveRecord::Base
  belongs_to :experimenter
  has_many :trials
  has_many :participants
end


class Trial < ActiveRecord::Base
  belongs_to :experiment
  belongs_to :datum
  belongs_to :condition
  has_one :result_trial
end

I would like to do a deep copy on objects including all the attributes.

The experiment_old is has 10 trials. And I want to copy everything to experiment_new with the 10 trials. experiment_old should also keep the 10 trial info.

However, all the cases I tried below, they copy everything well, but experiment_old does not have the 10 trials info. They just show up on experiment_new.

What is the best way to do deep copy for these cases.

case 1:

@experiment_new = Experiment.create(@experiment_old.attributes.merge(:trials => experiment_old.trails))

case 2:

@experiment_new = Marshal.load(Marshal.dump(@experiment_old.trials))

case 3:

@experiment_new = @experiment_old.clone

Here is the model:

class Experiment < ActiveRecord::Base
  belongs_to :experimenter
  has_many :trials
  has_many :participants
end


class Trial < ActiveRecord::Base
  belongs_to :experiment
  belongs_to :datum
  belongs_to :condition
  has_one :result_trial
end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鹤舞 2024-11-22 23:26:29

您可能会喜欢 ActiveRecord 3.2 的 Amoeba gem

它支持has_onehas_manyhas_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

,除了前缀之外,您还可以附加到给定字段或在给定字段上运行正则表达式

享受! :)

You may enjoy the Amoeba gem for ActiveRecord 3.2.

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.

be sure to check out the Amoeba Documentation but usage is pretty easy...

just

gem install amoeba

or add

gem 'amoeba'

to your Gemfile

then add the amoeba block to your model and run the dup method as usual

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:

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

权谋诡计 2024-11-22 23:26:29

您应该克隆每个试验并将它们分配给克隆的实验:

@experiment_new = @experiment_old.clone
@experiment_old.trials.each do |trial|
  @experiment_new.trials << trial.clone
end

You should clone every trial and assign them to the cloned experiment:

@experiment_new = @experiment_old.clone
@experiment_old.trials.each do |trial|
  @experiment_new.trials << trial.clone
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文