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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
# File 'lib/etna/clients/magma/workflows/walk_model_tree_workflow.rb', line 35
def walk_from(
model_name,
record_names = 'all',
model_attributes_mask: {},
model_filters: {},
page_size: 100,
&block)
q = [ { model_name: model_name, from: nil, record_names: record_names } ]
seen = Set.new
while (path = q.pop)
model_name = path[:model_name]
next if seen.include?([path[:from], model_name])
seen.add([path[:from], model_name])
template = template_for(model_name)
query_attributes, walk_attributes = masked_attributes(template: template, model_attributes_mask: model_attributes_mask, model_name: model_name)
request = RetrievalRequest.new(
project_name: magma_crud.project_name,
model_name: model_name,
record_names: path[:record_names],
filter: model_filters[model_name],
attribute_names: query_attributes,
page_size: page_size, page: 1
)
related_models = {}
magma_crud.page_records(model_name, request) do |response|
tables = []
collections = []
links = []
attributes = []
model = response.models.model(model_name)
template.attributes.attribute_keys.each do |attr_name|
next unless attribute_included?(query_attributes, attr_name)
attributes << attr_name
attr = template.attributes.attribute(attr_name)
if attr.attribute_type == AttributeType::TABLE
tables << attr_name
elsif attr.attribute_type == AttributeType::COLLECTION
related_models[attr.link_model_name] ||= Set.new
collections << attr_name
elsif attr.attribute_type == AttributeType::LINK
related_models[attr.link_model_name] ||= Set.new
links << attr_name
elsif attr.attribute_type == AttributeType::CHILD
related_models[attr.link_model_name] ||= Set.new
links << attr_name
elsif attr.attribute_type == AttributeType::PARENT && attribute_included?(walk_attributes, attr_name)
related_models[attr.link_model_name] ||= Set.new
links << attr_name
end
end
model.documents.document_keys.each do |key|
record = model.documents.document(key).slice(*attributes)
tables.each do |table_attr|
record[table_attr] = record[table_attr].map do |id|
response.models.model(template.attributes.attribute(table_attr).link_model_name).documents.document(id)
end unless record[table_attr].nil?
end
collections.each do |collection_attr|
record[collection_attr].each do |collected_id|
related_models[template.attributes.attribute(collection_attr).link_model_name].add(collected_id)
end unless record[collection_attr].nil?
end
links.each do |link_attr|
related_models[template.attributes.attribute(link_attr).link_model_name].add(record[link_attr]) unless record[link_attr].nil?
end
yield template, record
end
end
related_models.each do |link_model_name, id_set|
next if id_set.empty?
q.push({ model_name: link_model_name, from: model_name, record_names: id_set.to_a })
end
end
end
|