Ruby: refactor simple string method for aligning DSV text GOAL:


Accept DSV strings where the delimiter may consist of more than one character
Accept DSV strings where there are no embedded delimiters
Output text with no modification to the source string other than aligning custom delimiter with optional padding


QUESTION:


Anyone have a re-factor or stylistic enhancement or two?


CODE:

module DreftymacAddon
  module String
    ### &lt;region-fdef ddef="dsvpretty ;; lineup delims pretty print dsv text with lined up delimiters "&gt;
    def dsvpretty(delim=';;',padd='')
      sout    =   ""
      asizes  =   []
      alines  =   self.to_s.split(/[\x0a\x0d]/)
      alines.each{|currline|
        currline.split(delim).each_with_index{|currfld,icc|
          asizes[icc] = [asizes[icc].to_i,currfld.length].max()
        }
      }
      alines.each{|currline|
        next if currline.strip == ''
        atemp   = []
        currline.split(delim).each_with_index{|currfld,icc|
          atemp &lt;&lt; sprintf("%-#{asizes[icc]}s", currfld)
        }
        sout += atemp.join([padd , delim , padd].join(''))
        sout += "\n"
      }
      sout
    end
    alias :dsv_pretty :dsvpretty
    ### &lt;/region-fdef&gt;
  end
end

class String
  include DreftymacAddon::String
end


### String.new().dsvpretty ;; example usage
##{
if(1000!=0);
  vout   = %Q[
    LNAME|FNAME|AMOUNT|AGE|NATION|PLATFORM
    Rodriguez|Johan|30.00|58|uk|windows_xp
    Raynor|Coty|40.00|14|uk|redhat
    Bruen|Jackie|30.00|17|uk|ubuntu
    Breitenberg|Waldo|20.00|14|canada|mac_osx
    Collier|Lucy|30.00|22|canada|windows_vista
    Blick|Emmett|30.00|59|canada|knoppix
    Schroeder|Myrtis|10.00|29|uk|knoppix
    Rodriguez|Ashtyn|20.00|22|uk|mac_osx
    Leuschke|Sigmund|40.00|21|france|redhat
    Fahey|Cassidy|40.00|29|canada|knoppix    
  ]

  puts vout.dsvpretty('|','')
=begin
    LNAME      |FNAME  |AMOUNT|AGE|NATION|PLATFORM     
    Rodriguez  |Johan  |30.00 |58 |uk    |windows_xp   
    Raynor     |Coty   |40.00 |14 |uk    |redhat       
    Bruen      |Jackie |30.00 |17 |uk    |ubuntu       
    Breitenberg|Waldo  |20.00 |14 |canada|mac_osx      
    Collier    |Lucy   |30.00 |22 |canada|windows_vista
    Blick      |Emmett |30.00 |59 |canada|knoppix      
    Schroeder  |Myrtis |10.00 |29 |uk    |knoppix      
    Rodriguez  |Ashtyn |20.00 |22 |uk    |mac_osx      
    Leuschke   |Sigmund|40.00 |21 |france|redhat       
    Fahey      |Cassidy|40.00 |29 |canada|knoppix
=end  

  puts vout.dsvpretty('|',' ')
=begin
    LNAME       | FNAME   | AMOUNT | AGE | NATION | PLATFORM     
    Rodriguez   | Johan   | 30.00  | 58  | uk     | windows_xp   
    Raynor      | Coty    | 40.00  | 14  | uk     | redhat       
    Bruen       | Jackie  | 30.00  | 17  | uk     | ubuntu       
    Breitenberg | Waldo   | 20.00  | 14  | canada | mac_osx      
    Collier     | Lucy    | 30.00  | 22  | canada | windows_vista
    Blick       | Emmett  | 30.00  | 59  | canada | knoppix      
    Schroeder   | Myrtis  | 10.00  | 29  | uk     | knoppix      
    Rodriguez   | Ashtyn  | 20.00  | 22  | uk     | mac_osx      
    Leuschke    | Sigmund | 40.00  | 21  | france | redhat       
    Fahey       | Cassidy | 40.00  | 29  | canada | knoppix
=end    

end
##}
Some notes:


include DreftymacAddon::String. Monkeypatching common classes is always controversial, but in this case I wouldn't do it, it's not a general enough abstraction.
As always, I'd recommend using functional style with Ruby (if you check my other answers in this site, it's all I do ;-)) unless you have a very good reason not to. No sout = "", asize = [], each, array[key] = value, += and other statements, use expressions.
dsvpretty(delim=';;',padd=''). This kind of signature is problematic, if you want to set padd you are forced to set also delim when you wanted to keep the default value. Use an options hash instead. Note that finally Ruby 2.0 provides keyword arguments.
each_with_index{|currfld,icc|. Let the block breathe, and don't forget spaces after commas: each_with_index { |currfld, icc|. More on idiomatic Ruby.


I'd write:

module DreftymacAddon
  def self.dsv_pretty(string, options = {})
    options = {:delim =&gt; ";", :padding =&gt; ""}.merge(options)
    rows = string.strip.split(/\n/).map { |line| line.strip.split(options[:delim]) }
    columns_max_width = rows.map { |row| row.map(&amp;:size) }.transpose.map(&amp;:max)
    columns_separator = options[:padding] + options[:delim] + options[:padding]

    rows.map do |row|
      row.zip(columns_max_width).map do |cell, column_max_width|
        cell.ljust(column_max_width)
      end.join(columns_separator)
    end.join("\n")
  end
end

puts DreftymacAddon::dsv_pretty(vout, :delim =&gt; '|', :padding =&gt; " ")