public
Description: DeepCloning plugin
Homepage: http://blog.defv.be/2008/3/27/activerecord-deepclone-plugin
Clone URL: git://github.com/DefV/deep_cloning.git
deep_cloning / lib / deep_cloning.rb
100644 54 lines (48 sloc) 1.675 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# DeepCloning
 
module DeepCloning
  def self.included(base) #:nodoc:
    base.alias_method_chain :clone, :deep_cloning
  end
 
  # clones an ActiveRecord model.
  # if passed the :include option, it will deep clone the given associations
  # if passed the :except option, it won't clone the given attributes
  #
  # === Usage:
  #
  # ==== Cloning a model without an attribute
  # pirate.clone :except => :name
  #
  # ==== Cloning a model without multiple attributes
  # pirate.clone :except => [:name, :nick_name]
  # ==== Cloning one single association
  # pirate.clone :include => :mateys
  #
  # ==== Cloning multiple associations
  # pirate.clone :include => [:mateys, :treasures]
  #
  # ==== Cloning really deep
  # pirate.clone :include => {:treasures => :gold_pieces}
  #
  # ==== Cloning really deep with multiple associations
  # pirate.clone :include => [:mateys, {:treasures => :gold_pieces}]
  #
  def clone_with_deep_cloning options = {}
    kopy = clone_without_deep_cloning
    
    if options[:except]
      Array(options[:except]).each do |attribute|
        kopy.write_attribute(attribute, attributes_from_column_definition[attribute.to_s])
      end
    end
    
    if options[:include]
      Array(options[:include]).each do |association, deep_associations|
        if (association.kind_of? Hash)
          deep_associations = association[association.keys.first]
          association = association.keys.first
        end
        opts = deep_associations.blank? ? {} : {:include => deep_associations}
        kopy.send("#{association}=", self.send(association).collect {|i| i.clone(opts) })
      end
    end
 
    return kopy
  end
end