Ruby on Rails deep copy/ deep clone of object and its attributes

前端 未结 2 1434
刺人心
刺人心 2021-02-02 13:20

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

相关标签:
2条回答
  • 2021-02-02 13:49

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

    0 讨论(0)
  • 2021-02-02 13:50

    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
    
    0 讨论(0)
提交回复
热议问题