Class: Entity

Inherits:
Object
  • Object
show all
Defined in:
lib/og/entity/clone.rb

Class Method Summary collapse

Class Method Details

.clone(source, *args) ⇒ Object

Clones an object in every possible way (cannot copy HasMany but can copy all others - BelongsTo, etc). Provide a source object as first arguments, the rest (if any) are passed along to the initialize constructor when calling new to make the copied object.



88
89
90
91
92
93
94
95
96
# File 'lib/og/entity/clone.rb', line 88

def clone(source,*args)
  destination = source.class.new(*args)
  copy_properties(source, destination, [], false)
  # Must save here to copy join tables.      
  destination.save!
  copy_relations(source, destination, [])
  destination.save!
  destination
end

.copy_equal_relations(source, destination, ignore = []) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/og/entity/clone.rb', line 64

def copy_equal_relations(source, destination, ignore = [])
  source.class.relations.reject{|r| not [Og::JoinsMany, Og::ManyToMany].include?(r.class)}.each do |relation|
    next if relation.name == nil or ignore.include?(relation.name)
    source.send(relation.name).each do |related|
      destination.send(relation.name).send(:<<, related)
    end
  end
end

.copy_inferior_relations(source, destination, ignore = []) ⇒ Object

Copies relations of one record to another. Only copies has_one, refers_to, belongs_to relationships as has_many requires modifying of other objects and cannot be copied (by design). If you think you need to copy these relations, what you need is a joins_many relationship which can be copied.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/og/entity/clone.rb', line 45

def copy_inferior_relations(source, destination, ignore = [])
  real_ignore = Array.new
  
  # Map relation symbols to foreign keys.
  
  ignore.each do |symbol|
     source.class.relations.reject{|r| [Og::JoinsMany, Og::ManyToMany, Og::HasMany].include?(r.class)}.each do |relation|
       if relation.name == symbol.to_s
         real_ignore << relation.foreign_key.to_sym
         break
       end
     end
  end      
  
  # Use instance variable property copier method.
  
  property_copier(source, destination, real_ignore, false, true)
end

.copy_properties(source, destination, ignore = [], use_setter_method = false) ⇒ Object

Accepts source object, destination and ignore. Source and destination are self explanatory; ignore is a list of properties not to copy (i.e. :create_time,:update_time). By default sets the class variables directly on the remote model instance, if you set use_setter_method to true, uses create_time= style copying tactics,



34
35
36
# File 'lib/og/entity/clone.rb', line 34

def copy_properties(source, destination, ignore = [], use_setter_method = false)
  property_copier(source, destination, ignore, use_setter_method, false)
end

.copy_relations(source, destination, ignore = []) ⇒ Object

Copies all relations except HasMany which is impossible to copy. Use a JoinsMany relation instead if you need a copyable HasMany (which is irrational).



77
78
79
80
# File 'lib/og/entity/clone.rb', line 77

def copy_relations(source, destination, ignore = [])
  copy_inferior_relations(source, destination, ignore)
  copy_equal_relations(source, destination, ignore)
end

.property_copier(source, destination, ignore, use_setter_method, relations) ⇒ Object

Does the work of clone_properties and copy_inferior_relations. Syntax is the same with one extra field to tell the routine what it is copying.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/og/entity/clone.rb', line 102

def property_copier(source,destination,ignore,use_setter_method,relations)
  primary_key_symbol = source.class.primary_key.symbol
  source.class.properties.to_a.each do |symbol, property|
    next if primary_key_symbol == symbol or ignore.include?(symbol) or
     (relations and not property.relation) or (not relations and property.relation)
     
    variable = "@#{symbol}"
    if use_setter_method
      destination.send("#{symbol}=".to_sym,source.instance_variable_get(variable))
    else      
      destination.instance_variable_set(variable, source.instance_variable_get(variable))        
    end
  end
end