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
|
# frozen-string-literal: true
#
# The graph_each extension adds Dataset#graph_each and
# makes Dataset#each call #graph_each if the dataset has been graphed.
# Dataset#graph_each splits result hashes into subhashes per table:
#
# DB[:a].graph(:b, id: :b_id).all
# # => {:a=>{:id=>1, :b_id=>2}, :b=>{:id=>2}}
#
# You can load this extension into specific datasets:
#
# ds = DB[:table]
# ds = ds.extension(:graph_each)
#
# Or you can load it into all of a database's datasets, which
# is probably the desired behavior if you are using this extension:
#
# DB.extension(:graph_each)
#
# Related module: Sequel::GraphEach
#
module Sequel
module GraphEach
# Call graph_each for graphed datasets that are not being eager graphed.
def each
if @opts[:graph] && !@opts[:eager_graph]
graph_each{|r| yield r}
else
super
end
end
# Call graph_each for graphed datasets that are not being eager graphed.
def with_sql_each(sql)
if @opts[:graph] && !@opts[:eager_graph]
graph_each(sql){|r| yield r}
else
super
end
end
private
# Fetch the rows, split them into component table parts,
# tranform and run the row_proc on each part (if applicable),
# and yield a hash of the parts.
def graph_each(sql=select_sql)
# Reject tables with nil datasets, as they are excluded from
# the result set
datasets = @opts[:graph][:table_aliases].to_a.reject{|ta,ds| ds.nil?}
# Get just the list of table aliases into a local variable, for speed
table_aliases = datasets.map{|ta,ds| ta}
# Get an array of arrays, one for each dataset, with
# the necessary information about each dataset, for speed
datasets = datasets.map{|ta, ds| [ta, ds, ds.row_proc]}
# Use the manually set graph aliases, if any, otherwise
# use the ones automatically created by .graph
column_aliases = @opts[:graph][:column_aliases]
fetch_rows(sql) do |r|
graph = {}
# Create the sub hashes, one per table
table_aliases.each{|ta| graph[ta]={}}
# Split the result set based on the column aliases
# If there are columns in the result set that are
# not in column_aliases, they are ignored
column_aliases.each do |col_alias, tc|
ta, column = tc
graph[ta][column] = r[col_alias]
end
# For each dataset run the row_proc if applicable
datasets.each do |ta,ds,rp|
g = graph[ta]
graph[ta] = if g.values.any?{|x| !x.nil?}
rp ? rp.call(g) : g
else
nil
end
end
yield graph
end
self
end
end
Dataset.register_extension(:graph_each, GraphEach)
end
|