<img src=“https://travis-ci.org/moiristo/deep_cloneable.png?branch=master” alt=“Build Status” />
This gem gives every ActiveRecord::Base object the possibility to do a deep clone. It is a rails3 upgrade of the deep_cloning plugin (github.com/openminds/deep_cloning).
-
Ruby 1.8.7, 1.9.2, 1.9.3, 2.0.0, 2.1.5 (tested)
-
Activerecord 3.1, 3.2, 4.0, 4.1, 4.2
-
Rails 2.x/3.0 users, please check out the ‘rails2.x-3.0’ branch.
-
In your Gemfile:
gem ‘deep_cloneable’, ‘~> 2.1.0’
The ‘dup’ method with arguments has been replaced in deep_cloneable 2 by the method ‘deep_clone’. Please update your sources accordingly.
pirate.deep_clone :include => :mateys
pirate.deep_clone :include => [:mateys, :treasures]
pirate.deep_clone :include => {:treasures => :gold_pieces}
pirate.deep_clone :include => [:mateys, {:treasures => :gold_pieces}]
A dictionary ensures that models are not cloned multiple times when it is associated to nested models. When using a dictionary, ensure recurring associations are cloned first:
pirate.deep_clone :include => [:mateys, {:treasures => [:matey, :gold_pieces]}], :use_dictionary => true
If this is not an option for you, it is also possible to populate the dictionary manually in advance:
dict = { :mateys => {} } pirate.mateys.each{|m| dict[:mateys][m] = m.deep_clone } pirate.deep_clone :include => [:mateys, {:treasures => [:matey, :gold_pieces]}], :dictionary => dict
When an object isn’t found in the dictionary, it will be populated. By passing in an empty dictionary you can populate it automatically and reuse it in subsequent deep_clones to avoid creating multiples of the same object where you have overlapping associations.
pirate.deep_clone :except => :name
pirate.deep_clone :except => [:name, :nick_name]
pirate.deep_clone :include => :parrot, :except => [:name, { :parrot => [:name] }]
pirate.deep_clone :include => :parrot do |original, kopy| kopy.cloned_from_id = original.id if kopy.respond_to?(:cloned_from_id) end
Note: Using deep_clone with a block will also pass the associated objects that are being cloned to the block, so be sure to check whether the object actually responds to your method of choice.
pirate.deep_clone :include => {:treasures => :gold_pieces}, :validate => false
pirate.deep_clone :only => :name
pirate.deep_clone :only => [:name, :nick_name]
pirate.deep_clone :include => :parrot, :only => [:name, { :parrot => [:name] }]
pirate.deep_clone(:include => [{:treasures => { :gold_pieces => { :if => lambda{|piece| piece.is_a?(Parrot) } } } }, :mateys => { :unless => lambda{|matey| matey.is_a?(GoldPiece) } } ])
-
Fork the project.
-
Make your feature addition or bug fix.
-
Add tests for it. This is important so I don’t break it in a future version unintentionally.
-
Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
-
Send me a pull request. Bonus points for topic branches.
Copyright © 2015 Reinier de Lange. See LICENSE for details.