Class: Hirb::Helpers::Table
- Inherits:
-
Object
- Object
- Hirb::Helpers::Table
- Defined in:
- lib/hirb/helpers/table.rb
Direct Known Subclasses
Defined Under Namespace
Classes: TooManyFieldsForWidthError
Constant Summary collapse
- BORDER_LENGTH =
“ | ” and “-+-” are the borders
3
Class Method Summary collapse
-
.render(rows, options = {}) ⇒ Object
Main method which returns a formatted table.
Instance Method Summary collapse
-
#adjust_long_fields(field_lengths, max_width) ⇒ Object
Simple algorithm which given a max width, allows smaller fields to be displayed while restricting longer fields at an average_long_field_length.
-
#array_to_indices_hash(array) ⇒ Object
Converts an array to a hash mapping a numerical index to its array value.
-
#default_field_lengths ⇒ Object
find max length for each field; start with the headers.
-
#default_restrict_field_lengths(field_lengths, original_field_lengths, max_width) ⇒ Object
Produces a field_lengths which meets the max_width requirement.
- #filter_values(rows) ⇒ Object
- #format_cell(value, cell_width) ⇒ Object
-
#initialize(rows, options = {}) ⇒ Table
constructor
:stopdoc:.
- #render ⇒ Object
- #render_border ⇒ Object
- #render_footer ⇒ Object
- #render_header ⇒ Object
- #render_rows ⇒ Object
- #render_table_description ⇒ Object
- #render_table_header ⇒ Object
- #restrict_field_lengths(field_lengths, max_width) ⇒ Object
- #set_fields(rows) ⇒ Object
- #setup_field_lengths ⇒ Object
- #setup_rows(rows) ⇒ Object
- #validate_values(rows) ⇒ Object
Constructor Details
#initialize(rows, options = {}) ⇒ Table
:stopdoc:
66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/hirb/helpers/table.rb', line 66 def initialize(rows, ={}) @options = {:description=>true, :filters=>{}}.merge() @fields = set_fields(rows) @rows = setup_rows(rows) @headers = @fields.inject({}) {|h,e| h[e] = e.to_s; h} if @options.has_key?(:headers) @headers = @options[:headers].is_a?(Hash) ? @headers.merge(@options[:headers]) : (@options[:headers].is_a?(Array) ? array_to_indices_hash(@options[:headers]) : @options[:headers]) end if @options[:number] @headers[:hirb_number] = "number" @fields.unshift :hirb_number end end |
Class Method Details
.render(rows, options = {}) ⇒ Object
Main method which returns a formatted table.
Options:
- :fields
-
An array which overrides the default fields and can be used to indicate field order.
- :headers
-
A hash of fields and their header names. Fields that aren’t specified here default to their name. This option can also be an array but only for array rows.
- :field_lengths
-
A hash of fields and their maximum allowed lengths. If a field exceeds it’s maximum length than it’s truncated and has a … appended to it. Fields that aren’t specified here have no maximum allowed length.
- :max_width
-
The maximum allowed width of all fields put together. This option is enforced except when the field_lengths option is set. This doesn’t count field borders as part of the total.
- :number
-
When set to true, numbers rows by adding a :hirb_number column as the first column. Default is false.
- :filters
-
A hash of fields and the filters that each row in the field must run through. The filter converts the cell’s value by applying a given proc or an array containing a method and optional arguments to it.
- :vertical
-
When set to true, renders a vertical table using Hirb::Helpers::VerticalTable. Default is false.
- :all_fields
-
When set to true, renders fields in all rows. Valid only in rows that are hashes. Default is false.
- :description
-
When set to true, renders row count description at bottom. Default is true.
Examples:
Hirb::Helpers::Table.render [[1,2], [2,3]]
Hirb::Helpers::Table.render [[1,2], [2,3]], :field_lengths=>{0=>10}
Hirb::Helpers::Table.render [{:age=>10, :weight=>100}, {:age=>80, :weight=>500}]
Hirb::Helpers::Table.render [{:age=>10, :weight=>100}, {:age=>80, :weight=>500}], :headers=>{:weight=>"Weight(lbs)"}
Hirb::Helpers::Table.render [{:age=>10, :weight=>100}, {:age=>80, :weight=>500}], :filters=>{:age=>[:to_f]}
56 57 58 59 60 61 62 |
# File 'lib/hirb/helpers/table.rb', line 56 def render(rows, ={}) [:vertical] ? Helpers::VerticalTable.render(rows, ) : new(rows, ).render rescue TooManyFieldsForWidthError $stderr.puts "", "** Error: Too many fields for the current width. Configure your width " + "and/or fields to avoid this error. Defaulting to a vertical table. **" Helpers::VerticalTable.render(rows, ) end |
Instance Method Details
#adjust_long_fields(field_lengths, max_width) ⇒ Object
Simple algorithm which given a max width, allows smaller fields to be displayed while restricting longer fields at an average_long_field_length.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/hirb/helpers/table.rb', line 183 def adjust_long_fields(field_lengths, max_width) total_length = field_lengths.values.inject {|t,n| t += n} while total_length > max_width raise TooManyFieldsForWidthError if @fields.size > max_width.to_f / @min_field_length average_field_length = total_length / @fields.size.to_f long_lengths = field_lengths.values.select {|e| e > average_field_length} if long_lengths.empty? raise "Algorithm didn't work, resort to default" else total_long_field_length = (long_lengths.inject {|t,n| t += n}) * max_width/total_length average_long_field_length = total_long_field_length / long_lengths.size field_lengths.each {|f,length| field_lengths[f] = average_long_field_length if length > average_long_field_length } end total_length = field_lengths.values.inject {|t,n| t += n} end end |
#array_to_indices_hash(array) ⇒ Object
Converts an array to a hash mapping a numerical index to its array value.
251 252 253 |
# File 'lib/hirb/helpers/table.rb', line 251 def array_to_indices_hash(array) array.inject({}) {|hash,e| hash[hash.size] = e; hash } end |
#default_field_lengths ⇒ Object
find max length for each field; start with the headers
216 217 218 219 220 221 222 223 224 225 |
# File 'lib/hirb/helpers/table.rb', line 216 def default_field_lengths field_lengths = @headers ? @headers.inject({}) {|h,(k,v)| h[k] = String.size(v); h} : {} @rows.each do |row| @fields.each do |field| len = String.size(row[field]) field_lengths[field] = len if len > field_lengths[field].to_i end end field_lengths end |
#default_restrict_field_lengths(field_lengths, original_field_lengths, max_width) ⇒ Object
Produces a field_lengths which meets the max_width requirement
203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/hirb/helpers/table.rb', line 203 def default_restrict_field_lengths(field_lengths, original_field_lengths, max_width) original_total_length = original_field_lengths.values.inject {|t,n| t += n} relative_lengths = original_field_lengths.values.map {|v| (v / original_total_length.to_f * max_width).to_i } # set fields by their relative weight to original length if relative_lengths.all? {|e| e > @min_field_length} && (relative_lengths.inject {|a,e| a += e} <= max_width) original_field_lengths.each {|k,v| field_lengths[k] = (v / original_total_length.to_f * max_width).to_i } else # set all fields the same if nothing else works field_lengths.each {|k,v| field_lengths[k] = max_width / @fields.size} end end |
#filter_values(rows) ⇒ Object
227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/hirb/helpers/table.rb', line 227 def filter_values(rows) rows.map {|row| new_row = {} @fields.each {|f| if @options[:filters][f] new_row[f] = @options[:filters][f].is_a?(Proc) ? @options[:filters][f].call(row[f]) : row[f].send(*@options[:filters][f]) else new_row[f] = row[f] end } new_row } end |
#format_cell(value, cell_width) ⇒ Object
139 140 141 142 143 144 145 |
# File 'lib/hirb/helpers/table.rb', line 139 def format_cell(value, cell_width) text = String.size(value) > cell_width ? ( (cell_width < 5) ? String.slice(value, 0, cell_width) : String.slice(value, 0, cell_width - 3) + '...' ) : value String.ljust(text, cell_width) end |
#render ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/hirb/helpers/table.rb', line 108 def render body = [] unless @rows.length == 0 setup_field_lengths body += render_header body += render_rows body += end body << render_table_description if @options[:description] body.join("\n") end |
#render_border ⇒ Object
135 136 137 |
# File 'lib/hirb/helpers/table.rb', line 135 def render_border '+-' + @fields.map {|f| '-' * @field_lengths[f] }.join('-+-') + '-+' end |
#render_footer ⇒ Object
124 125 126 |
# File 'lib/hirb/helpers/table.rb', line 124 def [render_border] end |
#render_header ⇒ Object
120 121 122 |
# File 'lib/hirb/helpers/table.rb', line 120 def render_header @headers ? render_table_header : [render_border] end |
#render_rows ⇒ Object
147 148 149 150 151 152 153 |
# File 'lib/hirb/helpers/table.rb', line 147 def render_rows @rows.map do |row| row = '| ' + @fields.map {|f| format_cell(row[f], @field_lengths[f]) }.join(' | ') + ' |' end end |
#render_table_description ⇒ Object
155 156 157 158 |
# File 'lib/hirb/helpers/table.rb', line 155 def render_table_description (@rows.length == 0) ? "0 rows in set" : "#{@rows.length} #{@rows.length == 1 ? 'row' : 'rows'} in set" end |
#render_table_header ⇒ Object
128 129 130 131 132 133 |
# File 'lib/hirb/helpers/table.rb', line 128 def render_table_header title_row = '| ' + @fields.map {|f| format_cell(@headers[f], @field_lengths[f]) }.join(' | ') + ' |' [render_border, title_row, render_border] end |
#restrict_field_lengths(field_lengths, max_width) ⇒ Object
170 171 172 173 174 175 176 177 178 179 |
# File 'lib/hirb/helpers/table.rb', line 170 def restrict_field_lengths(field_lengths, max_width) max_width -= @fields.size * BORDER_LENGTH + 1 original_field_lengths = field_lengths.dup @min_field_length = BORDER_LENGTH adjust_long_fields(field_lengths, max_width) rescue TooManyFieldsForWidthError raise rescue default_restrict_field_lengths(field_lengths, original_field_lengths, max_width) end |
#set_fields(rows) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/hirb/helpers/table.rb', line 81 def set_fields(rows) if @options[:fields] @options[:fields].dup else if rows[0].is_a?(Hash) keys = @options[:all_fields] ? rows.map {|e| e.keys}.flatten.uniq : rows[0].keys keys.sort {|a,b| a.to_s <=> b.to_s} else rows[0].is_a?(Array) ? (0..rows[0].length - 1).to_a : [] end end end |
#setup_field_lengths ⇒ Object
160 161 162 163 164 165 166 167 168 |
# File 'lib/hirb/helpers/table.rb', line 160 def setup_field_lengths @field_lengths = default_field_lengths if @options[:field_lengths] @field_lengths.merge!(@options[:field_lengths]) else table_max_width = @options.has_key?(:max_width) ? @options[:max_width] : View.width restrict_field_lengths(@field_lengths, table_max_width) if table_max_width end end |
#setup_rows(rows) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/hirb/helpers/table.rb', line 94 def setup_rows(rows) rows ||= [] rows = [rows] unless rows.is_a?(Array) if rows[0].is_a?(Array) rows = rows.inject([]) {|new_rows, row| new_rows << array_to_indices_hash(row) } end rows = filter_values(rows) rows.each_with_index {|e,i| e[:hirb_number] = (i + 1).to_s} if @options[:number] validate_values(rows) rows end |
#validate_values(rows) ⇒ Object
242 243 244 245 246 247 248 |
# File 'lib/hirb/helpers/table.rb', line 242 def validate_values(rows) rows.each {|row| @fields.each {|f| row[f] = row[f].to_s || '' } } end |