-
Notifications
You must be signed in to change notification settings - Fork 371
Expand file tree
/
Copy pathsecure_eager_loader.rb
More file actions
77 lines (66 loc) · 2.98 KB
/
Copy pathsecure_eager_loader.rb
File metadata and controls
77 lines (66 loc) · 2.98 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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
module VCAP::CloudController::RestController
class SecureEagerLoader
def eager_load_dataset(dataset, starting_controller_class, default_visibility_filter, additional_visibility_filters, depth)
eager_load_hash = build_eager_load_hash(
starting_controller_class,
dataset.model,
default_visibility_filter,
additional_visibility_filters,
depth
)
dataset.eager(eager_load_hash)
end
private
def build_eager_load_hash(controller_class, model_class, default_visibility_filter, additional_visibility_filters, depth)
associated_controller = controller_class
# model_class cannot just be inferred from controller_class.model
# because ServiceInstancesController can be used to present objects
# from ManagedServiceInstance and ServiceInstance datasets.
# Ideally that will not happen.
associated_controller ||= VCAP::CloudController.controller_from_model_name(model_class.name)
all_relationships = {}
[associated_controller.to_one_relationships,
associated_controller.to_many_relationships].each do |rel|
all_relationships.merge!(rel) if rel&.any?
end
eager_load_hash = {}
all_relationships.each do |relationship_name, association|
association_name = association.association_name
association_model_class = model_class.association_reflection(association_name)
unless association_model_class
# Since we are using STI in some models (e.g. Domain, ServiceInstance)
# we are not able to find association on the parent class defined on a child class.
# We are assuming that parent will have an association with a suffix.
association_name = :"#{association_name}_sti_eager_load"
association_model_class = model_class.association_reflection(association_name)
end
unless association_model_class
raise ArgumentError.new(
"Cannot resolve association #{association_name} on #{model_class} " \
'while trying to build eager loading hash'
)
end
visibility_filter = default_visibility_filter
additional_filter = additional_visibility_filters[relationship_name]
visibility_filter = proc { |ds| additional_filter.call(default_visibility_filter.call(ds)) } if additional_filter
unless association.link_only?
if depth > 0
eager_load_hash[association_name] = {
visibility_filter => build_eager_load_hash(
nil,
association_model_class.associated_class,
default_visibility_filter,
additional_visibility_filters,
depth - 1
)
}
elsif association.is_a?(ControllerDSL::ToOneAttribute)
# Preload one-to-one since we need to know record's guid
eager_load_hash[association_name] = visibility_filter
end
end
end
eager_load_hash
end
end
end