preload
Jul 12

There are a lot of posts out there about how to add commas to numbers, but I haven’t seen any that showed how to make it a method of the built-in number types. Its very easy actually, but for those who are beginner Rubyists, here’s how I did it:


class Bignum

  def commas
    self.to_s =~ /([^\.]*)(\..*)?/
    int, dec = $1.reverse, $2 ? $2 : ""
    while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
    end
    int.reverse + dec
  end

end    

class Float

  def commas
    self.to_s =~ /([^\.]*)(\..*)?/
    int, dec = $1.reverse, $2 ? $2 : ""
    while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
    end
    int.reverse + dec
  end

end

class Fixnum

  def commas
    self.to_s =~ /([^\.]*)(\..*)?/
    int, dec = $1.reverse, $2 ? $2 : ""
    while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
    end
    int.reverse + dec
  end

end

Its the same function added to the three main number classes(Bignum, Float, and Fixnum). You would use them like so:

irb(main):001:0> require 'exo/format'
=> true
irb(main):002:0> g = 123456789
=> 123456789
irb(main):003:0> g.commas
=> "123,456,789"
irb(main):004:0> f = 123456.7891
=> 123456.7891
irb(main):005:0> f.commas
=> "123,456.7891"
irb(main):006:0> b = 12347862389461237846192873461287346
=> 12347862389461237846192873461287346
irb(main):007:0> b.commas
=> "12,347,862,389,461,237,846,192,873,461,287,346"
irb(main):008:0>

(exo/format is just the filename I use for the code above) These methods have the added benefit of converting the number into a string so you don’t have to convert before printing out.

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
May 22

Black Cat Systems sells a number of radiation meters that will capture and measure all kinds of radiation (Alpha, Beta, Gama, X-Ray, etc.). I bought one of these several years ago and recently unearthed it from my Pile of Forgotten Electronic Projects and hooked it up to one of my computers. The software that comes with it allows for an ftp upload, so I set it all up and its now uploading its readings to the RadMeter page every five minutes or so. Now you too can see if I’m living under fallout or not :)

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Apr 28

From my bag of tricks…

On occasion, I run into the need to present some kind of table information on to a console/terminal session so that the information is readable. After doing this several times, I decided to write a text table class so that i didn’t have to worry about formatting the table within my code. I just set the table up with column titles and column widths and just focus on the data.

Here’s the code:

#
#  texttable.rb  --  testing tool to output a nicely formatted table.
#
# John Allen, June 2005
#  June 2010 -- Added support for word wrap fields
#

class TextTable
  #
  # tableinfo = Hash.new {
  #    "name" =>  Array(:string),
  #    "width" => Array(:fixnum),
  #    ["linebetweenrows" => Boolean,]
  #    ["hdrlinechar" => "=",]
  #    ["rowlinechar" => "-",]
  #    ["wordwrap" => Boolean]
  # }

  attr_accessor  :names,  :widths, :hdr_print_flg, :lbr_flg, :hdrchar, :linechar, :wordwrap

  @hdr_print_flg = false
  @ldr_flg = false
  @wordwrap = false

  def initialize(tableinfo)
    @names = tableinfo["name"]
    @widths = tableinfo["width"]
    if tableinfo["linebetweenrows"]
      @lbr_flg = true
    end
    if tableinfo["wordwrap"]
      @wordwrap = true
    end
    @hdrchar = tableinfo["hdrlinechar"] || "="
    @linechar = tableinfo["rowlinechar"] || "-"
  end

  def printrow(a)
    # a = Array
    buf = ""
    if not @hdr_print_flg
      buf << printHdr()
    end
    buf << "|"
    extra = []
    a.each_with_index do |n,i|
      if n.length > @widths[i]        ## check to see if value is bigger than field; chop if so
        b = n.slice(0..(@widths[i] -1))
        extra[i] = n.slice(@widths[i]..-1)
      else
        b = n
      end
      buf << " #{b}#{" "*(@widths[i] - b.length)}|"
    end
    buf << "\n"
    if @wordwrap and not extra.empty?   ## Word Wrap
      eflg = true
      while eflg          ## While stuff to word wrap
        eflg = false
        buf << "|"
        extra.each_with_index do |n,i|
          if not n.nil?
            if n.length > @widths[i]        ## check to see if value is bigger than field; chop if so
              b = n.slice(0..(@widths[i] -1))
              extra[i] = n.slice(@widths[i]..-1)
              eflg = true           ## still more to word wrap!!
            else
              b = n
              extra[i] = nil
            end
            buf << " #{b}#{" "*(@widths[i] - b.length)}|"
          else
            buf << " #{" "*@widths[i]}|"  ## add blank space for non-wordwrap field
          end
        end
        buf << "\n"
      end
    end
    buf << _line(@linechar)  if @lbr_flg
    return buf
  end

  def printHdr
    buf = _line(@hdrchar)
    buf << "|"
    @names.each_with_index do |n,i|
      buf << " #{n}#{" "*(@widths[i] - n.length)}|"
    end
    buf << "\n"
    buf << _line(@hdrchar)
    @hdr_print_flg = true
    return buf
  end

  def printLine
    buf = _line(@linechar)
    return buf
  end

  #-------------------------------------------------------------------------------------------------------#
  private
  #-------------------------------------------------------------------------------------------------------#

  def _line(char)
    b = "+"
    @names.each_with_index do |n,i|
      b << char*@widths[i]
      b << "#{char}+"
    end
    b << "\n"
    return b
  end

end

if __FILE__ == $0
  tt = {
     "name" => ["First","Last","City","State"],
     "width" => [15,15,15,6],
     "linebetweenrows" => false
  }

  names = [
      ["John","Allen","Redmond","WA"],
      ["Herman","Gonzales","Mill Creek","WA"],
      ["Jimmy","Doogle","Bothell","WA"],
      ["Jane","Goodman","Seattle","WA"]
  ]

  table = TextTable.new(tt)

  buf = ""
  names.each do |name|
    buf << table.printrow(name)
  end
  buf << table.printLine
  puts buf

end

Running the example code at the bottom prints out the following result:

C:\Server4\Dev\Ruby\exo>ruby texttable.rb
+================+================+================+=======+
| First          | Last           | City           | State |
+================+================+================+=======+
| John           | Allen          | Redmond        | WA    |
| Herman         | Gonzales       | Mill Creek     | WA    |
| Jimmy          | Doogle         | Bothell        | WA    |
| Jane           | Goodman        | Seattle        | WA    |
+----------------+----------------+----------------+-------+

the printrow() method takes an array of String values to print out. You can have a line printed out between each row if you set the linebetweenrows hash value to ‘true’ (it defaults to ‘false’). There is not a lot of error checking (as in, you can crash the program if you feed the printrow() method an array that is shorter than the number of columns), but since I mainly use it for testing or utilities, I didn’t put a lot in. Its a very handy tool to have around.

Update: I added support for word wrap in all fields recently, so I have updated the code above with that version.

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Apr 21

One of my common Python tools: use this to list out all the directories from the specified root on down, ignoring some common directories that are specified in the program. You might want to modify this code to read in your ignore list. The program will also optionally take a size limit so that it only lists directories where the storage usage is over that limit.
Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Apr 14

Let the fun begin….

Microsoft has released the first official version of its Ruby integration with .NET called IronRuby 1.0. If you look closely to the release notes, you will see me on the list of bug reporters :) As I get more familiar with it, and feel I have something worth while to post, I’ll be blogging about it too.

You can download it from the IronRuby Download page.

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Apr 07

Every once and a while I get too fancy for my own good. :) A customer of mine has lots and lots (well…hundreds really) of Unix hosts that need updates of config files and such. There are lots of tools out there that can do what I need to do, but they all require an install on the nodes themselves. My customer does not want any extra software on these nodes, so to do any kind of automation requires me to upload the program, run it remotely, then remove it. I have a large number of tools to do all that several different ways.

Recently though, I needed to download a large file from each node while running another program on the node at the same time. Normally I would use SCP for the download part, but for reasons that would take too long to explain, that option was not open to me. So for some reason, I was struck with the ideal to just use a custom XMLRPC client/server to do the job. Turns out the code is pretty simple. My customer only has Python on these nodes, so my XMLRPC client is written in Python:

#
# xmlxfer.py
#
import xmlrpclib
import sys
import platform

port = 80    # Some port that passes through your firewall:  80, 21, 23, 25, etc.

farfname = sys.argv[1]
localfilename = sys.argv[2]
server = sys.argv[3]
#host = platform.uname()[1]
host = platform.node()
farname = host + "-" + farfname

ff = open(localfilename, "r").read()

svr = "http://" + server + ":" + port + "/RPC2"
xmlprxy = xmlrpclib.ServerProxy(svr)

print xmlprxy.xfer(farname, ff)

Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Mar 21

In my line of work I end up trying to move a large amount of text from web pages into things like Word and Excel. Getting the Text from the Web Browser is easy…Putting the text with formatting into an Office app could be a lot of work trying to parse through all the HTML and send the equivalent formatting commands with the text. Fortunately, Word and Excel had the ability to paste from the clipboard HTML and render it with the correct formatting! …Only problem is that for some reason, no one added HTML support in the Win32::Clipboard gem?!? (At least not in the 1.8.x version of Ruby, which I use.) So I spent a few hours looking over the existing clipboard.rb file, found a VBA example of an HTML Copy, and came up with the following code: Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Mar 16

If you try to “compile” a Ruby script that has the Watir gem in it with OCRA, you will find that running the compiled .exe file on a computer without the Watir gem previously being installed may result in this error:

c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie.rb:113:in `initialize': unknown OLE server: `AutoItX3.Control' (WIN32OLERuntimeError)
    HRESULT error code:0x800401f3
      Invalid class string      from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie.rb:113:in `new'
        from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie.rb:113:in `autoit'
        from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:425:in `autoit'
        from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:422:in `set_window_state'
        from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:398:in `maximize'
        ...

Huh? Why am I getting a WIN32OLE error? This all runs fine on my computer when I tested it! … Well, it seems that Watir uses its own version of a win32ole gem, and not the one that you already have installed. In fact, when you compile a Ruby script that has both win32ole and watir gems, you will need to comment out the “require ‘win32ole’” line in order for it to work. Anyway… as part of the win32ole gem install, it seems that it registers the AutoItX3.dll file into the registry. OCRA will, however, *NOT* copy this file over and register it for you, so you may see the error above.

So…the trick is add the AutoItX3.dll file to your OCRA compile, and to temporarily register the DLL before calling watir or win32ole commands. I simply copied the DLL from the win32ole gem directory to my Ruby script’s working directory, and then added it to my OCRA compile command:

C:\Server4\Dev\MyProg>ocra --console --icon c:/Server4/Dev/icons/exonets.ico myprog.rb AutoItX3.dll

OCRA will add the DLL to the EXE and when run will place it in the current temporary directory. After that you need to run the DLL register command to make it an OLE server, then when done, be sure to unregister it before your program completes.
Here a sample of code that I use to accomplish all this: Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Mar 04

Ever wanted to have a spell check function in your Ruby Program? As long as you have MS Word installed, you can use the Spellcheck function from your program. Here’s the code:

require 'exo/iswindows'

if not RUBY_PLATFORM.isWindows?
   puts "This program only runs under Windows!"
   exit
end

require 'win32ole'

def spellcheck(scstring)
   word = WIN32OLE.new('Word.Application')
   doc = word.Documents.Add     ## Blank document

   word.Selection.Text = scstring
   word.Dialogs(828).Show

   ### return the corrected text
   if not scstring[/ /]      ## only one word with no spaces in the string
     # highlight the word first,
     word.Selection.MoveLeft( 'Unit'=>2,
            'Count'=> 1,
            'Extend'=>2)
   end
   ## multiple words end up already selected after the spell check
   # then retrieve.
   correct = word.Selection.Text
   doc.close(0)
   word.Quit
   return correct
end

if __FILE__ == $0
   puts "Corrected => #{spellcheck(ARGV[0])}"
end

The program opens a new document, pastes the text to check into the document, and then brings up the spellcheck dialog box with any words it can’t find in the dictionary and prompts you to correct the mistakes. Here’s an sample output:

C:\Server6\Dev\Ruby>ruby spellcheck.rb "this is a test srting to seee how the slpell check is working"
Corrected => This is a test string to see how the spell check is working

C:\Server6\Dev\Ruby>ruby spellcheck.rb  antidisestablishmenttarianism
Corrected => antidisestablishmentarianism

For some reason, if you check multiple words, the dialog auto-closes after the last ‘fix’ …but if its just one word, it stays open until you click the close button. Conversely, multiple words stay selected in the Word doc after the dialog closes, but with only one word, it does not stay selected, and you have to select it back in order to read it off the page of the document.

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Feb 16

First off, let me say that there is not an original thought in any of this code, since it has all been taken from a number of different articles out on the Internet. The Daemonizing code was taken from the Active State Code Recipes area.

One of my customers has a number of database servers that we would like to monitor and see what the state of the clusters are. The problem is that the clustat command — that used to be run-able by everyone in a lesser version of RHEL — is now only usable by root in RHEL v5.3!. Not wanting to give out root access to everyone, we decided that a quick little custom server that provided the output of the clustat command in XML format would do the trick. Then I just wrote a Ruby program to query all the Clustat XML servers and display the results in a readable format. If there is enough interest, I can post a public version of that program.

Here’s the code: Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with: