Class: Ruport::Formatter::Text

Inherits:
Ruport::Formatter show all
Defined in:
lib/ruport/formatter/text.rb

Overview

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.

Instance Attribute Summary

Attributes inherited from Ruport::Formatter

#data, #format, #options

Instance Method Summary collapse

Methods inherited from Ruport::Formatter

build, #clear_output, #erb, formats, #method_missing, #output, renders, save_as_binary_file, #save_output, #template

Methods included from RenderingTools

#render_group, #render_grouping, #render_inline_grouping, #render_row, #render_table

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Ruport::Formatter

Instance Method Details

#apply_templateObject

Hook for setting available options using a template. See the template documentation for the available options and their format.



53
54
55
56
57
# 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

#build_group_bodyObject

Creates the group body. Since group data is a table, just uses the Table controller.



134
135
136
# File 'lib/ruport/formatter/text.rb', line 134

def build_group_body
  render_table data, options
end

#build_group_headerObject

Renders the header for a group using the group name.



127
128
129
# File 'lib/ruport/formatter/text.rb', line 127

def build_group_header
  output << "#{data.name}:\n\n"
end

#build_grouping_bodyObject

Generates the body for a grouping. Iterates through the groups and renders them using the group controller.



141
142
143
# File 'lib/ruport/formatter/text.rb', line 141

def build_grouping_body
  render_inline_grouping(options)
end

#build_row(data = self.data) ⇒ Object

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.



110
111
112
113
114
115
116
117
118
119
120
121
122
123
# 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

#build_table_bodyObject

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.



91
92
93
94
95
96
97
98
99
100
# 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

#build_table_headerObject

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.



73
74
75
76
77
78
79
80
81
# 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

#calculate_max_col_widthsObject

Determines the text widths for each column.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
# 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

#fit_to_width(s) ⇒ Object

Truncates a string so that it does not exceed Text#width



170
171
172
173
174
175
176
177
178
# 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

#hrObject

Generates the horizontal rule by calculating the total table width and then generating a bar that looks like this:

"+------------------+"


156
157
158
159
160
# 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

#max_col_widths_for_row(row) ⇒ Object

Used to calculate the max_col_widths array. Override this to tweak the automatic column size adjustments.



198
199
200
201
202
203
204
205
# 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

#prepare_tableObject

Checks to ensure the table is not empty and then calls calculate_max_col_widths.



62
63
64
65
66
# 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

#should_render_column_names?Boolean

Returns false if column_names are empty or options.show_table_headers is false/nil. Returns true otherwise.

Returns:

  • (Boolean)


148
149
150
# File 'lib/ruport/formatter/text.rb', line 148

def should_render_column_names?
  not data.column_names.empty? || !options.show_table_headers
end

#widthObject

Returns options.table_width if specified.

Otherwise, uses SystemExtensions to determine terminal width.



165
166
167
# File 'lib/ruport/formatter/text.rb', line 165

def width
  options.table_width ||= SystemExtensions.terminal_width
end