-
Notifications
You must be signed in to change notification settings - Fork 335
/
multi_builder.rb
101 lines (88 loc) · 2.81 KB
/
multi_builder.rb
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
module Rabl
class MultiBuilder
include Helpers
# Constructs a new MultiBuilder given the data and options.
# The options will be re-used for all Rabl::Builders.
# Rabl::MultiBuilder.new([#<User ...>, #<User ...>, ...], { :format => 'json', :child_root => true })
def initialize(data, settings = {}, options = {})
@data = data
@settings = settings
@options = options
@builders = []
@engine_to_builder = {}
@cache_key_to_engine = {}
end
# Returns the result of all of the builders as an array
def to_a
generate_builders
if template_cache_configured? && Rabl.configuration.use_read_multi
map_engines_to_builders
read_cache_results
replace_engines_with_cache_results
end
result = @builders.map(&:to_hash)
result = result.map(&:presence).compact if Rabl.configuration.exclude_empty_values_in_collections
result
end
private
# Creates a builder for each of the data objects
# and maps the cache keys for each of the engines
# the builders generated
def generate_builders
@builders = @data.map do |object|
Builder.new(object, @settings, @options)
end
end
def map_engines_to_builders
@builders.each do |builder|
builder.engines.each do |engine|
@engine_to_builder[engine] = builder
map_cache_key_to_engine(engine)
end
end
end
# Maps a cache key to an engine
def map_cache_key_to_engine(engine)
if cache_key = cache_key_for(engine)
result_cache_key = ActiveSupport::Cache.expand_cache_key(cache_key, :rabl)
@cache_key_to_engine[result_cache_key] = engine
disable_cache_read_on_render(engine)
end
end
def disable_cache_read_on_render(engine)
case engine
when Hash
disable_cache_read_on_render(engine.values.first)
when Engine
engine.cache_read_on_render = false
end
end
def cache_key_for(engine)
case engine
when Hash
cache_key_for(engine.values.first)
when Engine
engine.cache_key
end
end
# Returns the items that were found in the cache
def read_cache_results
@cache_results ||= begin
mutable_keys = @cache_key_to_engine.keys.map { |k| k.dup }
if mutable_keys.empty?
{}
else
Rabl.configuration.cache_engine.read_multi(*mutable_keys)
end
end
end
# Maps the results from the cache back to the builders
def replace_engines_with_cache_results
@cache_results.each do |key, value|
engine = @cache_key_to_engine[key]
builder = @engine_to_builder[engine]
builder.replace_engine(engine, value) if value
end
end
end
end