Archive

Posts Tagged ‘ruby’

Ruby CGI example

January 29th, 2010 dwright No comments

Searching for examples of ruby/cgi usage didn't turn up much.

I had to rough it and unfortunately, it took longer than it should have to come up with what I wanted to accomplish. (well, more or less what I wanted, well, actually, it's not going to work for what I need but anyway, here's an working ruby/cgi example).

thought I'd share:

require 'cgi'
require 'json'

cgi = CGI.new('html4Tr') # add HTML generation methods

if cgi.params.empty?
  # no request recieved, return html
  cgi.out('charset' => 'UTF-8') do
    cgi.html() do
      cgi.head() do
        "\n" +
        cgi.title{"cgi testing"} +
        CGI.pretty(
          "\n" + %q(<meta http-equiv="cache-control" content="no-cache">
          <meta http-equiv="content-type" content="text/html; charset=UTF-8">
          <meta http-equiv="expires" content="Mon, 22 Jul 2002 11:12:01 GMT">
          <meta http-equiv="pragma" content="no-cache">
          <script type="text/javascript" src="../js/jquery-1.3.2.js">)
        )
      end +
      cgi.body() do
        CGI.pretty(
          "\n" + %q(<input type='hidden' id="ids" value='' />
          <!-- start: show results -->
          <div id="show_hide_container" style="display:none"><a id="hide_n_show">[-]</a></div>
          <div id="action_results"></div>
          <!-- end: show results -->
          <div id="display_results">
            <div class="show_demo" id="unique" style="height:100%"></div>
          </div>)
        ) \
         +
        cgi.form() do
          cgi.textarea("get_text") +
          cgi.br +
          cgi.submit
        end +
        cgi.pre() do
          CGI::escapeHTML(
            "params: " + cgi.params.inspect + "\n" +
            "cookies: " + cgi.cookies.inspect + "\n" +
            ENV.collect() do |key, value|
              key + " --> " + value + "\n"
            end.join("")
          )
        end
      end
    end
  end
else
  # request recieved, return as JSON
  cgi = CGI.new(:encoding => 'UTF-8')
  print cgi.header('type' => 'application/x-javascript', 'charset' => 'UTF-8')
  print cgi.params.to_json
end
Categories: ruby Tags: , ,

Ruby, SQL Query result to iterable data structure

January 22nd, 2010 dwright No comments

This is an example of how to transform a multi-table join result returned by SQL and iterate over it to retrieve the data you are seeking.

Problem Space:

You have a multi-table join result returned by a SQL query which contains the data you need but in a 'flat' format which makes it difficult to extract, maintaing the data relationship.

The Data:

This data structure represents the data returned by a multi-table join.

sql_results = [
 {'t_name' => 'Acct & Benft','h_name' => 'Account',  'type' => 'pu_group'},
 {'t_name' => 'Acct & Benft','h_name' => 'Account',  'type' => 'py_group'},
 {'t_name' => 'Acct & Benft','h_name' => 'Account',  'type' => 'c_group'},
 {'t_name' => 'Acct & Benft','h_name' => 'Account',  'type' => 'pu_line'},
 {'t_name' => 'Acct & Benft','h_name' => 'Account',  'type' => 'py_line'},
 {'t_name' => 'Acct & Benft','h_name' => 'Account',  'type' => 'cl_line'},
 {'t_name' => 'Acct & Benft','h_name' => 'Benft',    'type' => 'b_line'},
 {'t_name' => 'Acct & Benft','h_name' => 'Benft',    'type' => 'b_c_line'},
 {'t_name' => 'Acct & Benft','h_name' => 'Benft',    'type' => 'b_c_add'},
 {'t_name' => 'Acct & Benft','h_name' => 'Benft',    'type' => 'b_group'},
 {'t_name' => 'Catg',        'h_name' => 'Catg Pge', 'type' => 'catg_line'},
 {'t_name' => 'Catg',        'h_name' => 'Catg Pge', 'type' => 'catg_group'},
 {'t_name' => 'List Page',   'h_name' => 'All St',   'type' => 's_line' },
 {'t_name' => 'List Page',   'h_name' => 'All St',   'type' => 's_group'},
 {'t_name' => 'List Page',   'h_name' => 'Cpns & S', 'type' => 'cpn_group'},
 {'t_name' => 'List Page',   'h_name' => 'Cpns & S', 'type' => 'cpn_line_a'},
 {'t_name' => 'List Page',   'h_name' => 'Cpns & S', 'type' => 'cpn_line'},
 {'t_name' => 'TLP',         'h_name' => 'Mrch Rand','type' => 'contact'},
 {'t_name' => 'TLP',         'h_name' => 'Mrch Rand','type' => 'tlp_group'},
 {'t_name' => 'TLP',         'h_name' => 'Mrch Rand','type' => 'tlp_line'}
]

From the data, I need to create a table where:

't_name' is a header with one or more sub-nodes, 'h_name'.
and 'h_name' is a sub-header with one or more sub-nodes, 'type'

For Illustration:

                          'List Page'(t_name)
                               |
               ----------------------------------
               |                                |
           'All St'(h_name)              'Cpns & S'(h_name)
               |                                |
         -------------             --------------------------
         |           |             |            |           |
      's_line', 's_group'     'cpn_group', 'cpn_line_a' 'cpn_line' (type)

Or, simpler

                          'Catg'(t_name)
                             |
                         'Catg Pge'(h_name)
                             |
                        -------------
                        |            |
                   'catg_line', 'catg_group'(type)

It seems clear, to me, that a good data structure for this representation would be
a hash whose key is t_name and whose values are a hash whose key is h_name and
whose value is an array

Example:

{
 "List Page" => {
      "All St"   => ["s_line", "s_group"],
      "Cpns & S" => ["cpn_group", "cpn_line_a", "cpn_line"]
  },
 "Catg"      => {
      "Catg Pge" => ["catg_line", "catg_group"]
  },
 etc,...

}

Here is some code which produces the desired data structure. (I'm sure there are many other approaches)

top_node     = Hash.new
top_sub_node = Hash.new
sql_results.each do |r|

  if top_sub_node[r['h_name']].nil?
    top_sub_node[r['h_name']] = [r['type']]
  else
    top_sub_node[r['h_name']].push r['type']
  end

  if top_node[r['t_name']].nil?
    top_node[ r['t_name'] ] = {r['h_name'] => top_sub_node[r['h_name']]}
  else
    top_node[ r['t_name'] ].merge!({r['h_name'] => top_sub_node[r['h_name']]})
  end
end

require 'pp'
pp top_node
Categories: ruby Tags: , ,

utf8 perl, ruby command line

July 8th, 2009 dwright No comments

String: Iñtërnâtiônàlizætiøn
- 20 characters
- 7 multi byte chars
- ñëâôàæø all have 2 bytes each
- string length is 27 bytes

% perl  -le 'print length "Iñtërnâtiônàlizætiøn"'
27

% ruby -e 'puts "Iñtërnâtiônàlizætiøn".length'
27

% ruby -le  'puts [73,195,177,116,195,171,114,110,195,162,116,105,195,180,110,195,160,108,105,122,195,166,116,105,195,184,110].pack("c*")'
Iñtërnâtiônàlizætiøn

% ruby -le  'puts "I" << [195,177].pack("cc") << "t" << "\303\253"   << "rn" << [195,162].pack("cc") << "ti" << [195,180].pack("cc") << "n" << [195,160].pack("cc") << "liz" << [195,166].pack("cc") << "ti" << [195, 184].pack("cc") << "n" '
Iñtërnâtiônàlizætiøn

% ruby -le  'puts "I\303\261t\303\253rn\303\242ti\303\264n\303\240liz\303\246ti\303\270n"'
Iñtërnâtiônàlizætiøn

% perl  -le 'print length "ñëâôàæø"'
14

% perl  -le 'print  "\xc3\xa6"'
æ
% ruby  -le 'print  "\xc3\xa6"'
æ
% perl  -le 'print  unpack 'U', "\xc3\xa6"'
195
% perl  -le 'print  unpack 'U', "\xa6"'
166
% perl  -le 'print unpack 'UU', "æ"'
195166
% perl  -le 'print unpack 'UUU', "æ"'
195166

% perl  -C2 -le 'print pack "U", 0xc3a6'

% perl  -le 'print pack("UU", 0xc3, 0xa6)'
æ
% perl  -le 'print pack("UU", 195, 166)'
æ

% perl  -le 'print unpack("UU", "ñ")'
195177
% perl  -le 'print pack("UU", 195,177)'
ñ
%  ruby  -le 'print [195,177].pack("cc")'
ñ

% perl -le 'print unpack("U*", "ë")'
195171

% perl -C2  -le 'print "\x{8482}\x{8480}\x{8481}\x{8483}\x{8484}"'
蒂蒀蒁蒃蒄
% ruby -e 'puts [0x8482,0x8480,0x8481,0x8483,0x8484].pack("U*")'
蒂蒀蒁蒃蒄
% perl -C2 -le 'print pack("U*", 0x8482,0x8480,0x8481,0x8483,0x8484)'
蒂蒀蒁蒃蒄

dwright@dwright-OSXL:[1139]:watir% ruby -v
ruby 1.8.7 (2009-04-08 patchlevel 160) [i686-darwin9]
dwright@dwright-OSXL:[1140]:watir% perl -v
This is perl, v5.8.9 built for darwin-2level

Categories: perl, ruby Tags: , , ,

windows cmd, ruby irb and utf-8

July 8th, 2009 dwright No comments

steps for viewing utf-8 chars in irb on windows:

A. set the console to use a TrueType font
B. set the console to use CP_UTF8 (set chcp 65001)
C. start irb via explicit path in ruby: ruby C:\Ruby\bin\irb

A1. open a cmd.exe, right click top of window -> properties (set to a TrueType font ;
I only have Lucida Console and Raster Fonts, so set to Lucida Console)

B1. C:\Documents and Settings\Administrator>chcp 65001

C1. C:\Documents and Settings\Administrator>Ruby C:\Ruby\bin\irb

2 example sessions

==========================
Session with non working utf8.
==========================
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\Administrator>
C:\Documents and Settings\Administrator>chcp
Active code page: 437

C:\Documents and Settings\Administrator>irb
irb(main):001:0> puts "\303\253"
ë
=> nil
irb(main):002:0>

after doing the above (ABC) steps:
==========================
Session with 'working' utf8. (sort of)
==========================
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\Administrator>

C:\Documents and Settings\Administrator>chcp 65001
Active code page: 65001

C:\Documents and Settings\Administrator>Ruby C:\Ruby\bin\irb
irb(main):001:0> puts "\303\253"
ëErrno::EACCES: Permission denied
from (irb):2:in `write'
from (irb):2:in `puts'
from (irb):2
irb(main):003:0> puts "\303\253\n"
ë
=> nil

(not sure what what the permission denied is all about but adding a newline removes the warning)

ok, now lets try for the utf-8 test, print the string: Iñtërnâtiônàlizætiøn

irb(main):017:0> s = 'I' << [195,177].pack('cc') << 't' << "\303\253" << 'rn' << [195,162].pack('cc') << 'ti' << [195,180].pack('cc') << 'n' << [195,160].pack('cc') << 'liz' << [195,166].pack('cc') << 'ti' << [195, 184].pack('cc') << 'n' => "I\303\261t\303\253rn\303\242ti\303\264n\303\240liz\303\246ti\303\270n"
irb(main):018:0> puts s+"\n"
Iñtërnâtiônàlizætiøn
tiøn
n
=> nil
irb(main):019:0> puts s+"\n"
Iñtërnâtiônàlizætiøn
tiøn
n
=> nil
irb(main):020:0> puts s
Iñtërnâtiônàlizætiønætiønnn
=> nil

irb(main):023:0> puts "I\303\261t\303\253rn\303\242ti\303\264n\303\240liz\303\246ti\303\270n"
Iñtërnâtiônàlizætiønætiønnn
=> nil

(ok, so it almost works,... - not sure what the extra 'n's and tiøn are all about)

references:
http://www.ruby-forum.com/topic/87447
http://blogs.msdn.com/michkap/archive/2006/03/06/544251.aspx
http://intertwingly.net/stories/2004/04/14/i18n.html

addendum:
If you are running Watir tests from the command line and want to be able to input strings into html form elments, such as str = 'Iñtërnâtiônàlizætiøn'.
do A1 and B1 above

Categories: ruby, windows Tags: , , ,

Ruby extended regular expression example

March 21st, 2009 dwright No comments

While looking for info on ruby's extended regular expression syntax, I didn't find many examples, so I created one.

Why would you want to use the extended feature of regular expressions?
One big reason is an increase in readability.

Problem space:

A company has a product code that is made up of 6 sections separated by a '-'
character. The rules for each section are as follows :

a 3 letter code, where the first letter can be any upper case letter, and the
other two can only be consonants.
a year
a 3 digit day number in a year
a 3 digit day number in a year
either H followed by a 3 digit even number or G followed by a 2 digit odd
number
A 4 digit hexadecimal number (i.e.usingthe letters A to F as digits)
Examples :

IPT-1996-123-256-H134-00DD

MNN-2004-056-178-G27-5D3F

Write a regular expression that will test against an arbitrary string to see
if contains a valid product code, it should not match against things that
ook
like product codes but which are surrounded by other numbers or letters :

Something like NNNNNNNNAWW-2010-123-256-H120-2BC34788 should NOT be matched.

Solution: (fairly adequate)

#!/usr/bin/env ruby

valid_3_pc = %w[
IPT-1996-123-256-H134-00DD
IPT-1996-123-256-H133-00DD
MNN-2004-056-178-G27-5D3F
PNN-2014-156-178-G25-1D3A
PNN-2014-156-178-G26-1D3A
BCA-8029-150-070-B21-00AA
ACBDDRFERMNN-2004-056-178-G27-5D3FIUD
ABMNN-2004-056-178-G27-5D3FAB456
MNN-204-056-178-G27-5D3FAB
NN-204-056-178-G27-5D3F
NNN-204-056-178-G7-5D3F
]

valid_pc = Regexp.new(
   '(^[A-Z]'            + # 3 letter code, #where the first letter can be any
                          # upper case letter
   '[A-Z\[^AEIOUY\]]'   +
   '{2})\-'             +
                          # the other two can only be consonants.
                          # seperated by hyphen (all upper case assumed)
   '(\d{4})\-'          + # a year (assumed max of 9999, min of 1000)
                          # seperated by hyphen
   '(\d{3})\-'          + # a 3 digit day number in a year (<365?)
                          # seperated by hyphen
   '(\d{3})\-'          + # a 3 digit day number in a year (<365?)
                          # seperated by hyphen
   '(H\d{3}|G\d{2})\-'  + # either H followed by a 3 digit even number or G
                          # followed by a 2 digit odd number
                          # seperated by hyphen
   '([A-Z0-9]{4})',       # A 4 digit hexadecimal number (i.e.using
                          # the letters A to F as digits)
                          # (all upper case assumed)
Regexp::EXTENDED)

# hopefully the above more readable then
#valid_pc = Regexp.new(
#  '(^[A-Z][A-Z\[^AEIOUY\]]{2})\-(\d{4})\-(\d{3})\-(\d{3})\-
(H\d{3}|G\d{2})\-([A-Z0-9]{4})', Regexp::EXTENDED
#) 

p valid_pc.to_s # see the regexp as string

valid_3_pc.each do |x|
  if x =~ valid_pc \
      && $3.to_i <= 365 \
      && $4.to_i <= 365 

    if $5[0,1] == 'H' \
        && (($5[1,$5.size].to_i % 2) == 0) # HDDD -> DDD has to be even
            puts "match: #{$1}-#{$2}-#{$3}-#{$4}-#{$5}-#{$6}\n"
    elsif $5[0,1] == 'G' \
        && (($5[1,$5.size].to_i % 2) != 0) # GDD -> GDD has to be odd
            puts "match: #{$1}-#{$2}-#{$3}-#{$4}-#{$5}-#{$6}\n"
    end

  end
end

Produces:

dwright@:[2706]:ruby% ruby product_codes.rb
"(?x-mi:(^[A-Z][A-Z\\[^AEIOUY\\]]{2})\\-(\\d{4})\\-(\\d{3})
\\-(\\d{3})\\-(H\\d{3}|G\\d{2})\\-([A-Z0-9]{4}))"
match: IPT-1996-123-256-H134-00DD
match: MNN-2004-056-178-G27-5D3F
match: PNN-2014-156-178-G25-1D3A
Categories: ruby Tags: ,