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
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
|
# File 'lib/curlybars/method_whitelist.rb', line 3
def allow_methods(*methods_without_type, **methods_with_type, &contextual_block)
methods_with_type_validator = lambda do |methods_to_validate|
methods_to_validate.each do |(method_name, type)|
if type.is_a?(Array)
next if generic_or_collection_helper?(type)
if type.size != 1 || !type.first.respond_to?(:dependency_tree)
raise "Invalid allowed method syntax for `#{method_name}`. Collections must be of one presenter class"
end
end
end
end
methods_with_type_validator.call(methods_with_type)
define_method(:allowed_methods) do
@method_whitelist_allowed_methods ||= begin
methods_list = methods_without_type + methods_with_type.keys
method_adder = lambda do |*more_methods, **more_methods_with_type|
methods_with_type_validator.call(more_methods_with_type)
methods_list += more_methods
methods_list += more_methods_with_type.keys
end
contextual_block&.call(self, method_adder)
defined?(super) ? super() + methods_list : methods_list
end
end
define_singleton_method(:methods_schema) do |context = nil|
all_methods_without_type = methods_without_type
all_methods_with_type = methods_with_type
schema_adder = lambda do |*more_methods_without_type, **more_methods_with_type|
methods_with_type_validator.call(more_methods_with_type)
all_methods_without_type += more_methods_without_type
all_methods_with_type = all_methods_with_type.merge(more_methods_with_type)
end
contextual_block&.call(context, schema_adder)
schema = all_methods_without_type.each_with_object({}) do |method, memo|
memo[method] = nil
end
methods_with_type_resolved = all_methods_with_type.transform_values do |type|
if type.respond_to?(:call)
type.call(context)
else
type
end
end
schema.merge!(methods_with_type_resolved)
schema.merge!(super(context)) if defined?(super)
included_modules.each do |mod|
next unless mod.respond_to?(:methods_schema)
schema.merge!(mod.methods_schema(context))
end
schema
end
define_singleton_method(:dependency_tree) do |context = nil|
methods_schema(context).each_with_object({}) do |method_with_type, memo|
method_name = method_with_type.first
type = method_with_type.last
memo[method_name] = if type.respond_to?(:dependency_tree)
type.dependency_tree(context)
elsif type.is_a?(Array)
if type.first == :helper
if type.last.is_a?(Array)
[:helper, [type.last.first.dependency_tree(context)]]
else
[:helper, type.last.dependency_tree(context)]
end
else
[type.first.dependency_tree(context)]
end
else
type
end
end
end
define_method(:allows_method?) do |method|
allowed_methods.include?(method)
end
define_method(:as_json) do |*args|
return @__as_json if defined?(@__as_json)
@__as_json ||= allowed_methods.each_with_object({}) do |method, hash|
unless self.method(method).arity > 0
value = send(method)
hash[method] = value.equal?(self) ? "[circular reference]" : value.as_json
end
end
end
end
|