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
|
# File 'lib/preload_pluck.rb', line 31
def preload_pluck(*args)
fields = args.map {|arg| Field.new(self, arg.to_s.split('.'))}
plucked_cols = fields.map do |field|
if field.nested?(0)
field.assoc(0).foreign_key
else
field.path.last
end
end.uniq
data = pluck(*plucked_cols)
if fields.length == 1
data.map! {|val| [val]}
end
data = __preload_pluck_to_attrs(data, plucked_cols)
joined_data = {}
max_level = fields.map {|f| f.path.length - 1}.max
max_level.times do |level|
fields.select {|f| f.nested?(level)}
.group_by {|f| f.path_upto(level)}
.each do |current_path, group|
assoc = group.first.assoc(level)
klass = assoc.class_name.constantize
if level == 0
collection = data
else
prev_path = group.first.path_upto(level - 1)
collection = joined_data[prev_path].values
end
ids = collection.map {|a| a[assoc.foreign_key]}.uniq
cols = group.map do |f|
if f.nested?(level + 1)
f.assoc(level + 1).foreign_key
else
f.path[level + 1]
end
end.uniq
joined_plucked_cols = [klass.primary_key, *cols]
joined = klass.where(klass.primary_key => ids).pluck(*joined_plucked_cols)
attrs = __preload_pluck_to_attrs(joined, joined_plucked_cols)
joined_data[current_path] = attrs.index_by {|a| a[klass.primary_key]}
end
end
data.map do |attr|
fields.map do |field|
if field.nested?(0)
assoc = field.assoc(0)
val = attr[assoc.foreign_key]
(field.path.length - 1).times do |level|
current_path = field.path_upto(level)
if field.nested?(level + 1)
col = field.assoc(level + 1).foreign_key
else
col = field.path.last
end
val = joined_data[current_path][val]
val = val[col] if val
end
val
else
attr[field.path.last]
end
end
end
end
|