Archive for the ‘Web Development’ Category

Building a better world with Google Spreadsheets

Released December 6th, 2006

I was tickled when I ran across the GoogleLookup and GoogleFinance functions in Google Spreadsheets. I was very tickled when I found there was a REST API for interacting with the spreadsheets.

So not only can you lookup the current volume of Google stock in a spreadsheet (=GoogleFinance(“GOOG”, “volume”)) or find out Roger Clemens’s ERA (=GoogleLookup(“Roger Clemens”,”earned run average”)) you can access those values real time using an open API. I cobbled together a quick ruby program that can retrieve values from a private or public (published) Google spreadsheet.

(more…)

IE7 adds native XMLHTTPRequest object

Released October 26th, 2006

The recently released IE7 supports a native XMLHTTPRequest object. On the surface this can be considered a good thing and should be commended. However, to the people that erroneously (in hindsight) assumed that…

window.XMLHttpRequest == ! (not) IE

…they are in for some strange behavior (here, here, here, and here for example).

The problem occurs when the code is optimized for non-IE browsers and does not recreate the XMLHTTPRequest object on each event. Back when “window.XMLHttpRequest == !IE” was true, this code worked as expected: IE browsers created a new XMLHttpRequest object on each event and non-IE browsers reused the same XMLHttpRequest object. Now IE7 will correctly process the first event but then fails on the second (and subsequent) requests because you still can’t reuse XMLHttpRequest objects.

We chose to just remove the optimization all together and recreate the object on each event for all browsers. Others may wish to come up with some other check that will allow them to keep it.

Cleaning Up Rails Sessions, Revisited

Released September 16th, 2006

In an earlier post, we detailed a method for removing stale Rails session files. In more recent version of Rails, there is a Rake task built in for this administration task.

rake tmp:sessions:clear # Clears all files in tmp/sessions

Cleaning up stale rails sessions (removing ruby_sess files)

Released June 8th, 2006

I’m not sure if something isn’t set up correctly of if this is just a fact of life with rails but the sessions it creates never seem to go away. I think before rails 1.1 the sessions where stored in /tmp and now they are stored in the apps directory along with everything else so they is probably no internal mechanism to delete them. I only noticed because after about a month of an certain app running the disk on the machine started to fill up. After digging a little I found 50K ruby_sess.* files hanging out in the rails session directory.

Anyway it was easy enough to clean up the stale ruby_sess files by going into the rails webapp/session directory and then running the following command:

find -type f -name "ruby_sess*" -exec rm -f {} \;

I’m not sure why the app is creating sessions but it isn’t something that stores state so I didn’t have to worry about killing active sessions here. If you do need to worry about that you will probably want to toss a time on the find command.

After looking a little more I found a post about this that has a ruby way of cleaning up the sessions.

Ruby’s DBI or ActiveRecord

Released 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…)

AJAX file upload progress for Java using commons fileupload and prototype

Released April 2nd, 2006

This has been done before with PHP (AJAX upload progress meter for PHP) etc but I needed something a little different because I wanted to upload a file and then have it loaded into a database. I looked around and found that someone had already made something that used the commons file upload package to do the upload part (AJAX Upload progress monitor for Commons-FileUpload Example). It wasn’t exactly what I was looking for but it a good start.

To understand the way this works I think it is easiest to break it down into parts:

  1. A file upload extention that counts bytes as they are uploaded
  2. An interface that monitors the progress of something running on the server
  3. AJAX to pull the monitoring into the current screen

(more…)

Credit card type and luhn check in ruby

Released 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

Released 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!

IE ‘Code’ bug

Released February 16th, 2006

We had a problem with how code was being displayed on the blog. IE wasn’t respecting the width of the code block and it was throwing the entire layout off.

Here is how I fixed it:

pre code {
 padding: 5px;
 display: block;
 overflow: auto;
/*I had to add this so ie wouldn't put scrollbars both ways.  Seems to be ignored by firefox*/
 overflow-y: visible;
/*I had to add this for ie to respect the width.  I don't know why it didn't respect its container's width*/
 width: 450px;
}

Smooth scrolling image list

Released February 15th, 2006

I had someone ask me about fitting more images in a small area and the way flickr does their image scrolling came to mind. I wanted to see how hard it was to do and as it turns out it isn’t hard to do at all thanks to script.aculo.us.

I’m making this as simple as I can to illustrate just how nice the new tools like script.aculo.us are.

Step 1. You need a box and some images. You will also need to know the size of the images or at least the size of the largest one. In an attempt to keep this simple I’m going to assume all the images are the same size.

<div id="imageBox">
  <div id="imageBoxInside">
    <img src="http://blogs.missiondata.com/wp-admin/images/turtle_sm_1.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/elephants_sm_1.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/turtle_sm_2.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/elephants_sm_2.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/turtle_sm_3.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/elephants_sm_3.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/turtle_sm_4.jpg" />
    <img src="http://blogs.missiondata.com/wp-admin/images/elephants_sm_4.jpg" />
    <br/>
  </div>
</div>

Notice from this code that we have an outer box and an inner box. We will next want to make the outer box smaller than the inner box so that only a few of the images can be seen at one time.

Step 2. To hide the extra images we give the outer box a set width, in this case I want to show only 2 images at a time and each image is 180px wide so I make the outer box 360px wide. Notice that the overflow is hidden. The hidden overflow is what keeps the images that are in the inner box but not within the outer box’s width hidden.

I’m using floats to lay the images out one next to the other. Because of this we need to give the inside box a large width so that it will not wrap the floated images.

<style type="text/css">
#imageBox { margin: auto; width: 360px; border: 1px #000 solid; overflow: hidden; }
#imageBoxInside { width: 10000px; }  #imageBox img { float: left; padding: 0px; margin: 0px; }
#imageBox br { clear: both; }
</style>

Step 3. Now for the magic. You need the latest version of script.aculo.us because I use the Effects.Move function and they have changed Effects.MoveBy to Effects.Move only recently.

We now create two functions to move the images ether one step to the right or one step to the left. Each step is the size of a single image so the when one is hit it moves one image out of thew view and another image into view. As you can see from the following code this is extremely easy using the script.aculo.us library.

<script>
function moveToPrevious()
{
  new Effect.Move('imageBoxInside', { x: 180, y: 0, transition: Effect.Transitions.sinoidal });
}  

function moveToNext()
{
  new Effect.Move('imageBoxInside', { x: -180, y: 0, transition: Effect.Transitions.sinoidal });
}
</script>

Step 4. The only thing that remains is to connect everything together. We add a couple links to move call the next and previous functions defined above.

< a href="javascript:void(0);" href="javascript:void(0);" onclick="moveToPrevious(); return true;"><img src="http://blogs.missiondata.com/wp-admin/images/previous.png" />
< a href="javascript:void(0);" href="javascript:void(0);" onclick="moveToNext(); return true;"><img src="http://blogs.missiondata.com/wp-admin/images/next.png" />

And that is all there is to it. See it in action!