ActiveRecord: How can I clone nested associations?

前端 未结 5 1157
星月不相逢
星月不相逢 2020-12-05 18:17

I\'m currently cloning a single-level association like this:

class Survey < ActiveRecord::Base
  def duplicate
    new_template = self.clone
    new_templ         


        
5条回答
  •  粉色の甜心
    2020-12-05 18:28

    You may also like the Amoeba gem for ActiveRecord 3.2.

    In your case, you probably want to make use of the nullify, regex or prefix options available in the configuration DSL.

    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
    

    You can also control which fields get copied in numerous ways, but for example, if you wanted to prevent comments from being duplicated but you wanted to maintain the same tags, you could do something like this:

    class Post < ActiveRecord::Base
      has_many :comments
      has_and_belongs_to_many :tags
    
      amoeba do
        exclude_field :comments
      end
    end
    

    You can also preprocess fields to help indicate uniqueness with both prefixes and suffixes as well as regexes. In addition, there are also numerous options so you can write in the most readable style for your purpose:

    class Post < ActiveRecord::Base
      has_many :comments
      has_and_belongs_to_many :tags
    
      amoeba do
        include_field :tags
        prepend :title => "Copy of "
        append :contents => " (copied version)"
        regex :contents => {:replace => /dog/, :with => "cat"}
      end
    end
    

    Recursive copying of associations is easy, just enable amoeba on child models as well

    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
    

    The configuration DSL has yet more options, so be sure to check out the documentation.

    Enjoy! :)

提交回复
热议问题