class Ruport::Formatter::Text
This class provides text output for Ruport's Row, Table, Group, and Grouping controllers
It handles things like automatically truncating tables that go off the edge of the screen in the console, proper column alignment, and pretty output that looks something like this:
+------------------------------+ | apple | banana | strawberry | +------------------------------+ | yes | no | yes | | yes | yes | red snapper | | what | the | red snapper | +------------------------------+
Supported Options ¶ ↑
:max_col_width:
Ordinal array of column widths. Set
automatically but can be overridden.
:alignment:
Defaults to left justify text and right justify
numbers. Centers all fields when set to :center.
:table_width:
Will truncate rows at this limit.
:show_table_headers:
Defaults to true
:show_group_headers:
Defaults to true
:ignore_table_width:
When set to true, outputs full table
without truncating it. Useful for file output.
Public Instance Methods
Hook for setting available options using a template. See the template documentation for the available options and their format.
# File lib/ruport/formatter/text.rb, line 53 def apply_template apply_table_format_template(template.table) apply_column_format_template(template.column) apply_grouping_format_template(template.grouping) end
Creates the group body. Since group data is a table, just uses the Table controller.
# File lib/ruport/formatter/text.rb, line 134 def build_group_body render_table data, options end
Renders the header for a group using the group name.
# File lib/ruport/formatter/text.rb, line 127 def build_group_header output << "#{data.name}:\n\n" end
Generates the body for a grouping. Iterates through the groups and renders them using the group controller.
# File lib/ruport/formatter/text.rb, line 141 def build_grouping_body render_inline_grouping(options) end
Generates a formatted text row.
Defaults to numeric values being right justified, and other values being left justified. Can be changed to support centering of output by setting options.alignment to :center
Uses #fit_to_width to truncate the row if necessary.
# File lib/ruport/formatter/text.rb, line 110 def build_row(data = self.data) max_col_widths_for_row(data) unless options.max_col_width data.enum_for(:each_with_index).inject(line=[]) { |s,e| field,index = e if options.alignment.eql? :center line << field.to_s.center(options.max_col_width[index]) else align = field.is_a?(Numeric) ? :rjust : :ljust line << field.to_s.send(align, options.max_col_width[index]) end } output << fit_to_width("| #{line.join(' | ')} |\n") end
Generates the body of the text table.
Defaults to numeric values being right justified, and other values being left justified. Can be changed to support centering of output by setting options.alignment to :center
Uses #fit_to_width to truncate the table if necessary.
# File lib/ruport/formatter/text.rb, line 91 def build_table_body output << fit_to_width(hr) return if data.empty? calculate_max_col_widths unless options.max_col_width data.each { |row| build_row(row) } output << fit_to_width(hr) end
Uses the column names from the given Data::Table to generate a table header.
Calls #fit_to_width to truncate the table heading if necessary.
# File lib/ruport/formatter/text.rb, line 73 def build_table_header return unless should_render_column_names? c = data.column_names.enum_for(:each_with_index).map { |f,i| f.to_s.center(options.max_col_width[i]) } output << fit_to_width("#{hr}| #{c.join(' | ')} |\n") end
Determines the text widths for each column.
# File lib/ruport/formatter/text.rb, line 181 def calculate_max_col_widths # allow override return if options.max_col_width options.max_col_width = [] unless data.column_names.empty? data.column_names.each_index do |i| options.max_col_width[i] = data.column_names[i].to_s.length end end data.each { |r| max_col_widths_for_row(r) } end
Truncates a string so that it does not exceed #width
# File lib/ruport/formatter/text.rb, line 170 def fit_to_width(s) return s if options.ignore_table_width # workaround for Rails setting terminal_width to 1 max_width = width < 2 ? 80 : width s.split("\n").each { |r| r.gsub!(/\A.{#{max_width+1},}/) { |m| m[0,max_width-2] + ">>" } }.join("\n") + "\n" end
Generates the horizontal rule by calculating the total table width and then generating a bar that looks like this:
"+------------------+"
# File lib/ruport/formatter/text.rb, line 156 def hr ref = data.column_names.empty? ? data[0].to_a : data.column_names len = options.max_col_width.inject(ref.length * 3) {|s,e|s+e} "+" + "-"*(len-1) + "+\n" end
Used to calculate the max_col_widths
array. Override this to
tweak the automatic column size adjustments.
# File lib/ruport/formatter/text.rb, line 198 def max_col_widths_for_row(row) options.max_col_width ||= [] row.each_with_index do |f,i| if !options.max_col_width[i] || f.to_s.length > options.max_col_width[i] options.max_col_width[i] = f.to_s.length end end end
Checks to ensure the table is not empty and then calls calculate_max_col_widths.
# File lib/ruport/formatter/text.rb, line 62 def prepare_table raise Ruport::FormatterError, "Can't output table without " + "data or column names." if data.empty? && data.column_names.empty? calculate_max_col_widths end
Returns false if column_names are empty or options.show_table_headers is false/nil. Returns true otherwise.
# File lib/ruport/formatter/text.rb, line 148 def should_render_column_names? not data.column_names.empty? || !options.show_table_headers end
Returns options.table_width if specified.
Otherwise, uses SystemExtensions to determine terminal width.
# File lib/ruport/formatter/text.rb, line 165 def width options.table_width ||= SystemExtensions.terminal_width end
Private Instance Methods
# File lib/ruport/formatter/text.rb, line 218 def apply_column_format_template(t) t = (t || {}).merge(options.column_format || {}) options.max_col_width ||= t[:maximum_width] options.alignment ||= t[:alignment] end
# File lib/ruport/formatter/text.rb, line 224 def apply_grouping_format_template(t) t = (t || {}).merge(options.grouping_format || {}) options.show_group_headers = t[:show_headings] if options.show_group_headers.nil? end
# File lib/ruport/formatter/text.rb, line 209 def apply_table_format_template(t) t = (t || {}).merge(options.table_format || {}) options.show_table_headers = t[:show_headings] if options.show_table_headers.nil? options.table_width ||= t[:width] options.ignore_table_width = t[:ignore_width] if options.ignore_table_width.nil? end