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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
# File 'lib/view_model/active_record/cloner.rb', line 15
def clone(node)
reset_state!
new_model = node.model.dup
pre_visit(node, new_model)
return nil if ignored?
if node.class.name
class_name = node.class.name.underscore.gsub('/', '__')
visit = :"visit_#{class_name}"
end_visit = :"end_visit_#{class_name}"
end
if visit && respond_to?(visit, true)
self.send(visit, node, new_model)
return nil if ignored?
end
ignored_associations = @ignored_associations
node.class._members.each do |name, association_data|
next unless association_data.is_a?(ViewModel::ActiveRecord::AssociationData)
reflection = association_data.direct_reflection
if ignored_associations.include?(name)
new_associated = association_data.collection? ? [] : nil
else
associated = node.model.public_send(reflection.name)
if associated.nil?
new_associated = nil
elsif !association_data.owned? && !association_data.through?
new_associated = associated
else
build_vm = ->(model) do
vm_class =
if association_data.through?
association_data.direct_viewmodel
else
association_data.viewmodel_class_for_model!(model.class)
end
vm_class.new(model)
end
new_associated =
if ViewModel::Utils.array_like?(associated)
associated.map { |m| clone(build_vm.(m)) }.compact
else
clone(build_vm.(associated))
end
end
end
new_association = new_model.association(reflection.name)
new_association.writer(new_associated)
end
if end_visit && respond_to?(end_visit, true)
self.send(end_visit, node, new_model)
end
post_visit(node, new_model)
new_model
end
|