Archive for the 'ruby' Category

Ruby’s DBI or ActiveRecord

Sunday, April 9th, 2006

While creating a small CGI web application in Ruby the question came up about how much slower ActiveRecord is than DBI. Considering that ActiveRecord is initialized each time the CGI runs the performance hit could be significant.

So why not use Rails instead? The server that I am running the application on has limited resources. Rails is reported to need about 20 MB of memory and the node I have is already paging out memory to disk.

To emulate the webserver getting hit repeatedly with connections I created a connect_dbi.rb and and connect_ar.rb that insert the same row into a Tests database table. The ActiveRecord test also has the model file test.rb

The test was run using a PostGreSQL database on Ubuntu 5.10 with Ruby 1.8.4. The table was truncated between tests. I just wanted to get an idea of the performance difference between ActiveRecord and DBI. So this isn’t the strictest performance test but does provide an idea of the magnitude of difference.

(more…)

Seeing Ruby

Wednesday, April 5th, 2006

This past Friday I participated in my first presentation, Seeing Ruby: An Introduction to the Ruby Programming Language at the iTRC in Louisville, Kentucky. Chuck Fouts, Steven Yelton, and I did our level best to introduce our audience to one of our favorite development tools. Our audience was fantastic, and had lots of questions. Everyone stayed a good 15 minutes after the official end to finish Steven’s awesome Rails demo.

Honestly, Ruby sells itself though. People tend to sit up and notice blocks and open classes.

We’ll be posting the presentation slides very soon to the permanent page. And as we take the show to other venues we’ll be tweaking and refining the content. Initial feedback is to beef up the handout with a cheatsheet of language features; our whirlwind tour of the language goes by quickly and some sort of reference will help keep everything together.

Our audience expressed great interest in Ruby on Rails and AJAX, even a few requests for some Seeing More Ruby classes. We’re debating on whether “You’ll Be Seeing AJAX” or “You’ll Be Seeing Rails” next. :) Let us know which you’d rather see.

Incidentally, we’re also taking this presentation to a company for a private show, and we’d be willing to come talk with you and your colleagues as well. Just contact us!

Streaming data to S3 with ruby

Wednesday, March 29th, 2006

One of the downsides of the ruby S3 example code is that it doesn’t support streaming of data (it loads the entire file into memory). It turns out, however, that all that is needed to stream data is a tweak to the ‘request’ method in Net::HTTP.

  require 'net/http'
require 'S3'
require 'pp'

#
# Replace the request method in Net::HTTP to sniff the body type
# and set the stream if appropriate
#
module Net
  class HTTP
    alias __request__ request

    def request(req, body = nil, &block)
      if body != nil && body.respond_to?(:read)
        req.body_stream = body
        return __request__(req, nil, &block)
      else
        return __request__(req, body, &block)
      end
    end
  end
end

#
# Connect to s3 using the ruby API provided by Amazon
#
conn = S3::AWSAuthConnection.new("[PUBLIC]", "[PRIVATE]", false)

#
# Stream a testfile to S3
#
open("testfile") do |stream|
  pp response = conn.put('BUCKET_NAME',
                         "testfile",
                         stream,
                         {
                           "x-amz-acl" => "public-read",
                           "Content-Type" => "text/plain",
                           "Content-Length" =>  FileTest.size("testfile").to_s
                         }
                        )
end

#
# Send a testfile in memory to S3
#
pp response = conn.put('BUCKET_NAME',
                       "testfile",
                       File.read('testfile'),
                       {
                         "x-amz-acl" => "public-read",
                         "Content-Type" => "text/plain"
                       }
                      )

  

A few notes about the code

  • When streaming you have to supply the ‘Content-Length’ header
  • I had an error about S3.rb calling strip on non-strings, I changed line 49 to ‘interesting_headers[lk] = value.to_s.strip’
  • Make sure you replace PUBLIC, PRIVATE, and BUCKET_NAME with appropriate values

Offloading web traffic using Amazon’s S3 service

Tuesday, March 28th, 2006

We have a couple of fairly high traffic sites that have large images designed to be used for desktop backgrounds. To save a bit of bandwidth, we decided to give Amazon’s S3 webservice a spin.

Signing up was fairly painless. They required a credit card (so they could bill us $.15/G storage and $.20/G transfer). After I signed up I quickly received an email that contained a link to my public and secret keys.

This is a fairly new service and the client tools are just getting started. For my purposes of uploading several images, I decided to use jSh3ll to ‘browse’ my S3 storage and a custom ruby script to upload a large amount of files.

After downloading and installing jSh3ll, I created my first bucket:
(more…)

Ruby Oracle DBI ActiveRecord in 7 steps

Wednesday, March 22nd, 2006

Setting up ruby to work with Oracle seems to be a pain for a lot of people. Here are the steps I follow to set it up on a linux box from nothing to Active Record or DBI in 7 steps.

  1. Gather the installation sources you will need. You have to be registered with oracle to get their instant client packages.
    Download the ruby oci8 drivers
    Download the oracle instant client
    You want the following packages (these examples assume the zip format):

    • Instant Client Package - Basic or Instant Client Package - Basic Lite
    • Instant Client Package - SDK
    • Instant Client Package - SQL*Plus (optional but nice to have)
  2. (more…)

Credit card type and luhn check in ruby

Wednesday, March 15th, 2006

I was looking at implementing a luhn and credit card type check the other day in java and I noticed that there seems to be a lack of code for doing this in ruby. So I figured I would put something together for doing the checks in ruby.

The following function will do a luhn check for a given number (any number not just credit card numbers). The luhn algorithm is fairly simple, if you want to learn more about it check here.

def luhnCheck(ccNumber)
  ccNumber = ccNumber.gsub(/\\D/, '')
  cardLength = ccNumber.length
  parity = cardLength % 2

  sum = 0
  for i in 0...cardLength
    digit = ccNumber[i] - 48

    if i % 2 == parity
      digit = digit * 2
    end

    if digit > 9
      digit = digit - 9
    end

    sum = sum + digit
  end

  return (sum % 10) == 0
end

Before running the luhn check you may want to verify that you have a valid card type or at least one you want to accept. The following function will do that based on the current bin ranges for the differenct companies as of today (for more on this see the following: credit card number information and BIN range information). N.B. Bin ranges change from time to time so this will become dated. It should be easy enough to find the updated ranges.

def ccTypeCheck(ccNumber)
  ccNumber = ccNumber.gsub(/\\D/, '')
  case ccNumber
    when /^3[47]\\d{13}$/ then return "AMEX"
    when /^4\\d{12}(\\d{3})?$/ then return "VISA"
    when /^5\\d{15}|36\\d{14}$/ then return "MC"
    when /^6011\\d{12}|650\\d{13}$/ then return "DISC"
    when /^3(0[0-5]|8[0-1])\\d{11}$/ then return "DINERS"
    when /^(39\\d{12})|(389\\d{11})$/ then return "CB"
    when /^3\\d{15}|1800\\d{11}|2131\\d{11}$/ then return "JCB"
    else return "NA"
  end
end

quick and dirty ruby

Thursday, February 16th, 2006

At work I received an email from someone that listed libraries I should use when connecting to their AS400 system. I wanted a quick way to convert their whitespace table into a nice comma-separated list. Below is the first 6 lines from about 50 or so.

Sequence
 number   Library
    10    QTEMP            

    20    DDMFLIB2
....

If it’s computable but a one-off, I immediately go to Ruby nowadays. 10 years ago it would have been Perl, 15 or 20 years ago the choice would have been probably a meld of sed|awk.

I always go with __END__ in these situations; Ruby stops processing at the __END__ line, but you are given an enumerable access to the contents that follow with the magical DATA object.

matches = DATA.collect { |line| line.match(/\\\\s+\\\\d+\\\\s+(\\\\w+)/) }
matches.compact!
puts matches.collect { |match| match[1] }.join(', ')

__END__
Initial library list:                            

Sequence
 number   Library
    10    QTEMP            

    20    DDMFLIB2
    30    APPSDEV
    50    FILES2                                                       

   110    QRPG                                                              

Let’s try it out (running Ruby/Windows in a Cygwin terminal):

dday@xpmachine21 ~
$ ruby liblist.rb
QTEMP, DDMFLIB2, APPSDEV, FILES2, QRPG

Success!