lib/hirb/helpers/table.rb in hirb-0.2.2 vs lib/hirb/helpers/table.rb in hirb-0.2.3

- old
+ new

@@ -22,11 +22,12 @@ # +-----+--------+ # # By default, the fields/columns are the keys of the first hash. #-- # derived from http://gist.github.com/72234 -class Hirb::Helpers::Table +module Hirb + class Helpers::Table BORDER_LENGTH = 3 # " | " and "-+-" are the borders class TooManyFieldsForWidthError < StandardError; end class << self @@ -42,31 +43,31 @@ # 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. # 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]} def render(rows, options={}) - options.delete(:vertical) ? Hirb::Helpers::VerticalTable.render(rows, options) : new(rows, options).render + options.delete(:vertical) ? Helpers::VerticalTable.render(rows, options) : new(rows, options).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. **" - Hirb::Helpers::VerticalTable.render(rows, options) + Helpers::VerticalTable.render(rows, options) end end #:stopdoc: def initialize(rows, options={}) @options = options @options[:filters] ||= {} - @fields = @options[:fields] ? @options[:fields].dup : ((rows[0].is_a?(Hash)) ? rows[0].keys.sort {|a,b| a.to_s <=> b.to_s} : - rows[0].is_a?(Array) ? (0..rows[0].length - 1).to_a : []) + @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]) @@ -74,11 +75,24 @@ if @options[:number] @headers[:hirb_number] = "number" @fields.unshift :hirb_number end end - + + 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 + def setup_rows(rows) rows ||= [] rows = [rows] unless rows.is_a?(Array) if rows[0].is_a?(Array) rows = rows.inject([]) {|new_rows, row| @@ -121,17 +135,17 @@ def render_border '+-' + @fields.map {|f| '-' * @field_lengths[f] }.join('-+-') + '-+' end def format_cell(value, cell_width) - text = value.length > cell_width ? + text = String.size(value) > cell_width ? ( - (cell_width < 5) ? value.slice(0,cell_width) : value.slice(0, cell_width - 3) + '...' + (cell_width < 5) ? String.slice(value, 0, cell_width) : String.slice(value, 0, cell_width - 3) + '...' ) : value - sprintf("%-#{cell_width}s", text) + String.ljust(text, cell_width) end - + def render_rows @rows.map do |row| row = '| ' + @fields.map {|f| format_cell(row[f], @field_lengths[f]) }.join(' | ') + ' |' @@ -146,11 +160,11 @@ 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] : Hirb::View.width + 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 def restrict_field_lengths(field_lengths, max_width) @@ -198,14 +212,14 @@ end end # find max length for each field; start with the headers def default_field_lengths - field_lengths = @headers ? @headers.inject({}) {|h,(k,v)| h[k] = v.length; h} : {} + field_lengths = @headers ? @headers.inject({}) {|h,(k,v)| h[k] = String.size(v); h} : {} @rows.each do |row| @fields.each do |field| - len = row[field].length + len = String.size(row[field]) field_lengths[field] = len if len > field_lengths[field].to_i end end field_lengths end @@ -237,5 +251,6 @@ def array_to_indices_hash(array) array.inject({}) {|hash,e| hash[hash.size] = e; hash } end #:startdoc: end +end \ No newline at end of file