Tech Tidbits - Ruby, Ruby On Rails, Merb, .Net, Javascript, jQuery, Ajax, CSS...and other random bits and pieces.

Tuesday, November 18, 2008

Nginx, Mongrel, Merb

Quick notes on installing and configuring nginx and running with existing mongrel and Merb app on my MacBookPro.

1) Download and install PCRE (if needed)

$ ./configure
$ ./make
$ ./make install

2) Download and install nginx:
The latest stable version is nginx-0.6.32, the change log.

$ ./configure
$ ./make
$ ./make install

# Edit nginx.conf file (/usr/local/nginx/conf/nginx.conf)
# Note - based on Ezra's blog post (see notes below)

user nobody;
worker_processes 2;

error_log logs/error.log notice;
pid logs/;

events {
worker_connections 1024;

http {
include mime.types;
#include conf/mime.types;
default_type application/octet-stream;

# no sendfile on OSX uncomment
#this if your on linux or bsd
#sendfile on;
tcp_nopush on;

keepalive_timeout 65;
tcp_nodelay on;

upstream mongrel {

gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;

server {
listen 80;
#server_name localhost;
root /Users/dsparlingimbp/git/dougsparlingdotcom/public;

access_log off;
rewrite_log on;

location ~ ^/$ {
if (-f /index.html){
rewrite (.*) /index.html last;
proxy_pass http://mongrel;

location / {
if (!-f $request_filename.html) {
proxy_pass http://mongrel;
rewrite (.*) $1.html last;

location ~ .html {
root /Users/dsparlingimbp/git/dougsparlingdotcom/public;

location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov)$ {
root /Users/dsparlingimbp/git/dougsparlingdotcom/public;

location / {
proxy_pass http://mongrel;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


4) Commands for starting and stopping nginx
start: sudo /usr/local/nginx/sbin/nginx
stop: sudo kill `cat /usr/local/nginx/logs/`

5) Start Mongrel cluster (I'm using 3 Mongrels):
$ merb -c 3
$ merb -p 4000 -c 3

6) Resources

Sunday, November 9, 2008

Ruby - Randomize arrays and strings

Randomize the elements of an array:

random_array = my_array.sort_by{rand}

Randomize a string (jumble a given word):

jumbled_word = word.split("").sort_by{rand}.join

Saturday, November 8, 2008

Updating to RubyGems 1.3.0 on Mac OS X Leopard 10.5.4

When attempting to stall final release of Merb 1.0, I got an error message that I needed RubyGems version >=1.3.0:

ERROR: Error installing merb:
merb-core requires RubyGems version >= 1.3.

So I did the usual "gem update --system" but got an error:

$ sudo gem update --system
Updating RubyGems
Updating rubygems-update
Successfully installed rubygems-update-1.3.0
ERROR: While executing gem ... (NameError)
undefined local variable or method `remote_gemspecs' for #
$ gem --version

I found that you have to run a second set of instructions:

$ sudo gem install rubygems-update
Successfully installed rubygems-update-1.3.0
1 gem installed
$ sudo update_rubygems
Installing RubyGems 1.3.0

More info here:

Wednesday, August 27, 2008

Dynamic Details Row in GridView

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web.Configuration" %>

<script runat="server">

void GridView1_PreRender(object sender, EventArgs e)
if (GridView1.SelectedRow != null)
Table table = GridView1.SelectedRow.Parent as Table;

if (table != null)
CreateRow(table, GridView1.SelectedIndex);

void CreateRow(Table table, int index)
GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);
table.Rows.AddAt(index + 2, row);

private TableCell CreateColumn()
TableCell cell = new TableCell();
cell.ColumnSpan = GridView1.Columns.Count;
cell.Width = Unit.Percentage(100);

DataSourceControl ds = CreateDataSourceControl();

return cell;

private static DetailsView CreateDetailsView(DataSourceControl ds)
DetailsView dv = new DetailsView();
dv.AutoGenerateRows = true;
dv.DataSourceID = ds.ID;
return dv;

private DataSourceControl CreateDataSourceControl()

SqlDataSource ds = new SqlDataSource();
ds.ConnectionString = WebConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
ds.SelectCommand = "SELECT * FROM [Users] WHERE [UserID] = @UserID";
ds.ID = "SqlDataSource2";

Parameter cp = new Parameter("UserID", TypeCode.String, GridView1.SelectedValue.ToString());
return ds;


<html xmlns="" >

<head id="Head1" runat="server">
<title>Untitled Page</title>

<form id="form1" runat="server">

 <asp:GridView ID="GridView1" Runat="server" DataSourceID="SqlDataSource1" DataKeyNames="UserID"
AutoGenerateColumns="False" OnPreRender="GridView1_PreRender" EnableViewState="False">
<asp:CommandField ShowSelectButton="True">
<asp:BoundField ReadOnly="True" HeaderText="UserID" DataField="UserID" SortExpression="UserID">
<asp:BoundField HeaderText="UserName" DataField="UserName" SortExpression="UserName"></asp:BoundField>

<asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT [UserID], [UserName] FROM [Users]"
ConnectionString="<%$ ConnectionStrings:MyConnectionString %>">



Saturday, August 23, 2008

Amazon S3 with Ruby aws-s3 gem

I stated using Amazon S3 to store and backup the music I've written and recorded. I'm using the Ruby aws-s3 gem. Note that I check for some basic audio file types so I don't have to manually type the bucket or mime-type.

#!/usr/bin/env ruby
require 'rubygems'
require 'aws/s3'

# File to upload
local_file = ARGV[0]

# bucket & mime-type
if local_file =~ /mp3$/
bucket = 'doug_mp3'
mime_type = 'audio/mpeg'
elsif local_file =~ /wav$/
bucket = 'doug_wav'
mime_type = 'audio/x-wav'
elsif local_file =~ /aif[c|f]?$/
bucket = 'doug_aiff'
mime_type = 'audio/x-aiff'
bucket = ARGV[1]
mime_type = ARGV[2] || "application/octet-stream"

if bucket.nil?
puts "need a bucket"

puts "file: #{local_file}"
puts "bucket: #{bucket}"
puts "mime_type: #{mime_type}"

:access_key_id => 'REPLACE_ME',
:secret_access_key => 'REPLACE_ME'

base_name = File.basename(local_file)

puts "Uploading #{local_file} as '#{base_name}' to '#{bucket}'"
:content_type => mime_type

puts "Uploaded!"

I can call the script a couple ways:

# with defaults based on extension
$ ruby aws-s3.rb mysong.mp3

# or explicitly (file, bucket, mime-type)
$ ruby aws-s3.rb mysong.mp3 doug_mp3 'audio/mp3'

Add and remove a remote source from gem 'remote sources''

I was attempting to add a gem and ran into an error I hadn't seen before:

Macintosh:aws-s3 dsparlingimbp$ sudo gem i aws-s3
WARNING: RubyGems 1.2+ index not found for:

RubyGems will revert to legacy indexes degrading performance.
Updating metadata for 63 gems from
ERROR: could not find gem aws-s3 locally or in a repository

So I tried to update gems:

Macintosh:aws-s3 dsparlingimbp$ sudo gem update --system
Updating RubyGems
WARNING: RubyGems 1.2+ index not found for:

RubyGems will revert to legacy indexes degrading performance.
Updating metadata for 63 gems from
ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError)
bad response Not Found 404 (

Next I looked the gems environment:

Macintosh:rubygems-1.2.0 dsparlingimbp$ gem env
RubyGems Environment:
- RUBY VERSION: 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.8.5]
- INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8
- RUBY EXECUTABLE: /usr/local/bin/ruby
- EXECUTABLE DIRECTORY: /usr/local/bin
- ruby
- x86-darwin-8
- /usr/local/lib/ruby/gems/1.8
- :update_sources => true
- :verbose => true
- :benchmark => false
- :backtrace => false
- :bulk_threshold => 1000
- :sources => ["", ""]

Noticing the issues with Merb (which I recently installed), I removed from the list of remote sources:

sudo gem sources -r

I went ahead and added github while I was at it:

sudo gem sources -a

Checked my gems environment:

Macintosh:rubygems-1.2.0 dsparlingimbp$ gem env
RubyGems Environment:
- RUBY VERSION: 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.8.5]
- INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8
- RUBY EXECUTABLE: /usr/local/bin/ruby
- EXECUTABLE DIRECTORY: /usr/local/bin
- ruby
- x86-darwin-8
- /usr/local/lib/ruby/gems/1.8
- :update_sources => true
- :verbose => true
- :benchmark => false
- :backtrace => false
- :bulk_threshold => 1000
- :sources => ["", ""]

Everything looked good, so I tried to install aws-s3 gem again:

Macintosh:rubygems-1.2.0 dsparlingimbp$ sudo gem install aws-s3
Successfully installed aws-s3-0.5.1
1 gem installed
Installing ri documentation for aws-s3-0.5.1...
Installing RDoc documentation for aws-s3-0.5.1...

Et VoilĂ ! C'est si bon...

Saturday, July 26, 2008

authentication token

I had a need to both validate the source of data sent to a web service and to only accept the data if it was sent within a limited time period. One thing I didn't need, (but I imagine would be necessary in most cases) was to only allow the request once, in which case you would probably want to store the token in a database and flag it once it had been "redeemed."

To create the token, first concatenate current time in epoch seconds (or whatever time format you like, but stick with UTC since the end user may be any where in the world), username, and a password, then m5d and base64 that concatenated string and prepend it with the same timestamp, separated by a colon (':').

require 'digest/md5'
require 'base64'

# Username/password
UID = 'marypoppins'
PWD = "supercalifragilisticexpialidocious"

# create token using utc secconds, uid, and pwd
def create_token(t=nil)
timestamp = t ||
plaintext = timestamp + UID + PWD
md5 = Digest::MD5.digest(plaintext)
return timestamp + ':' + Base64.encode64(md5).strip

# validate token
def validate_token(token)
token_timestamp = token.split(':')[0]
token2 = create_token(token_timestamp)
return token == token2 ? true : false

# validate timestamp and token
def validate_token_and_timestamp(token,num_secs=60)
token_timestamp = token.split(':')[0]
return nil if - token_timestamp.to_i > num_secs
token2 = create_token(token_timestamp)
return token == token2 ? true : false

The most basic example: create a token and validate it by creating a new token using the timestamp in the original token with the known user id and password. If the two tokens match, the original token is valid (which it will be in this contrived example):

# create a token and validate
if (validate_token(create_token))
puts "Valid token"
puts "Invalid token"

To check if the token was passed within a certain time period, just compare the timestamp on the original token with current time.

# create a token and validate timestamp and token
if (validate_token_and_timestamp(create_token,10))
puts "Valid token"
puts "Invalid token"

For demonstration only, use sleep to timeout a token:

# create a token, but let token timeout before trying to validate
timeout_token = create_token
sleep 15
if (validate_token_and_timestamp(timeout_token,10))
puts "Valid token"
puts "Invalid token"

Monday, July 21, 2008

Self Referential Associations with has_many :through


class CreateTeletubbies < ActiveRecord::Migration
def self.up
create_table :teletubbies do |t|
t.string :name
Teletubby.create(:name => 'Tinky Winky')
Teletubby.create(:name => 'Dipsy')
Teletubby.create(:name => 'Laa Laa')
Teletubby.create(:name => 'Po')

def self.down
drop_table :teletubbies


class CreateFriendships < ActiveRecord::Migration
def self.up
create_table :friendships do |t|
t.integer :teletubby_id
t.integer :friend_id
# Tinky Winky loves all the other Teletubbies very much
Friendship.create(:teletubby_id => 1, :friend_id => 2)
Friendship.create(:teletubby_id => 1, :friend_id => 3)
Friendship.create(:teletubby_id => 1, :friend_id => 4)
# Dipsy loves all the other Teletubbies very much
Friendship.create(:teletubby_id => 2, :friend_id => 1)
Friendship.create(:teletubby_id => 2, :friend_id => 3)
Friendship.create(:teletubby_id => 2, :friend_id => 4)
# Laa Laa loves Po very much
Friendship.create(:teletubby_id => 3, :friend_id => 4)
# Po loves Laa Laa very much
Friendship.create(:teletubby_id => 4, :friend_id => 3)
# Big Hug

def self.down
drop_table :friendships


class Teletubby < ActiveRecord::Base
# a teletubby 'has_many' friendships (teletubbies love each other very much)
has_many :friendships

# a teletubby 'has_many' friends ':through' friendships relationship
has_many :friends, :through => :friendships


class Friendship < ActiveRecord::Base
# ActiveRecord already knows what a teletubby is (reflection)
belongs_to :teletubby

# No actual friendship model, so add :class_name and :foreign_key
belongs_to :friend, :class_name => "Teletubby", :foreign_key => "friend_id"

The database should look a little something like this:

mysql> select * from teletubbies;
| id | name | created_at | updated_at |
| 1 | Tinky Winky | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 2 | Dipsy | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 3 | Laa Laa | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 4 | Po | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
4 rows in set (0.00 sec)

mysql> select * from friendships;
| id | teletubby_id | friend_id | created_at | updated_at |
| 1 | 1 | 2 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 2 | 1 | 3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 3 | 1 | 4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 4 | 2 | 1 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 5 | 2 | 3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 6 | 2 | 4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 7 | 3 | 4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 8 | 4 | 3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
8 rows in set (0.00 sec)

Use script/console to check the relationships:

dsparling-imbps-computer:~/Sites/teletubbies dsparlingimbp$ script/console
Loading development environment (Rails 2.0.2)
>> t1 = Teletubby.find(1)
=> #<Teletubby id: 1, name: "Tinky Winky", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42">
>> t1.friends.each { |f| puts "#{} loves #{} very much." }; false
Tinky Winky loves Dipsy very much.
Tinky Winky loves Laa Laa very much.
Tinky Winky loves Po very much.
=> false
>> t2 = Teletubby.find(2)
=> #<Teletubby id: 2, name: "Dipsy", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42">
>> t2.friends.each { |f| puts "#{} loves #{} very much." }; false
Dipsy loves Tinky Winky very much.
Dipsy loves Laa Laa very much.
Dipsy loves Po very much.
=> false
>> t3 = Teletubby.find(3)
=> #<Teletubby id: 3, name: "Laa Laa", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42">
>> t3.friends.each { |f| puts "#{} loves #{} very much." }; false
Laa Laa loves Po very much.
=> false
>> t4 = Teletubby.find(4)
=> #<Teletubby id: 4, name: "Po", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42">
>> t4.friends.each { |f| puts "#{} loves #{} very much." }; false
Po loves Laa Laa very much.
=> false

Saturday, July 12, 2008

Screencast Addiction


Rails Conf(s)
The RubyFringe Videos


ThoughtWorks IT Matters and ThoughtWorks Talks
Gooogle search railsconf
Google search oscon
InfoQ Presentations



I have an old SanDisk mp3 player that I use to listen to music and podcasts. Though it's a rather small card (512M), it's still annoying to have to scroll through my single playlist to get to a specific file.

The SanDisk sorts by the mp3 info title tag, so I wrote a small script that I run on my podcast files before I load them on my player so that they will show up first in the playlist by prepending '01_' to the mp3 title tag (and using the mp3 filename if the title is nil).

First, install the ruby-mp3info gem if you don't have it:

gem install ruby-mp3info


require 'rubygems'
require "mp3info"

dir ='/Users/dsparlingimbp/PODCAST/mp3')
puts "mp3 directory: #{dir.path}"

dir.each do |file|
next unless /\.mp3$/ =~ file
puts "mp3: #{file}"

mp3file = "#{dir.path}/#{file}" do |mp3|
puts "original title: #{mp3.tag.title}"
title = '01_' + (mp3.tag.title || file)
mp3.tag.title = title
puts "new title: #{mp3.tag.title}"


Friday, July 11, 2008

Podcast Addiction

It's bad enough that I subscribe to more RSS feeds than I can possibly read in a day, but I've also become addicted to podcasts...many are tech podcasts, but I listen to a wide variety...

From my current iTunes podcasts directory:

Andy Jordan's Tech Diary
Audible Ajax
The Bugle
The Christian Science Monitor - News
Digital Media Insider
The Flex Show (podcast and screencast)
FOO Casts
The French Pod Class
IT Conversations
L33t Tech News
Learning Rails (now a screencast)
.NET Rocks!
podcasts - Channel 9
Pragmatic Programmers
Radio Allegro
Rails Envy Podcast
Railscasts (screencast)
Ruby on Rails Podcast
The Thirsty Developer
This American Life
Wall Street Journal Tech News Briefings
Wall Street Journal on Small Business
Wall Street Journal's Your Money Matters
The Washington Institute Podcast
The Web 2.0 Show
Web Design TV

A few others:
French Vibes

And a couple of "top tech podcasts" links:
The top 40 tech podcasts - .net magazine
Top 10 Best Technology Podcasts

Thursday, July 10, 2008

Ignore exisiting directory in subverion Rails repo

I needed to ignore the log directory of an existing Rails app I had checked out:

svn up
svn delete log
svn commit -m 'removed log dir'
mkdir log
svn add --non-recursive log
svn propset svn:ignore "*" log/
svn commit -m "Add log dir, ignore contents"

With a little help from:

Tuesday, June 3, 2008

CocoaMySQL - MySQL GUI for Mac OS X

I had to restore a MySQL database dump to a server at new host with no shell access. The host recommended SQLyog, but I'm working on this project on my Mac, and SQLyog is Windows only.

CocoaMySQL was a quick and easy install and did exactly what I needed.

Of course, on my Mac itself, it was the standard MySQL command:

$ mysql -h localhost -u root myshinynewdb < mydatabasedump.sql

Sunday, June 1, 2008

CSS, Firefox - font-family, form intput and textarea

I'll do my own write up at some point, but ran across this, which solved a problem I was having with FF:

Thursday, May 22, 2008

cache_fu: Conditional action-caching stops after a period of time


module ActsAsCached
module FragmentCache
def self.setup!
class << CACHE
include Extensions


# add :ttl option to cache helper and set cache store memcache object
def self.setup_rails_for_memcache_fragments
if ::ActionView.const_defined?(:Template)
# Rails 2.1+
::ActionController::Base.cache_store = CACHE
# Rails < svn r8619
::ActionView::Helpers::CacheHelper.class_eval do
def cache(name = {}, options = nil, &block)
@controller.cache_erb_fragment(block, name, options)
::ActionController::Base.fragment_cache_store = CACHE

def self.setup_fragment_cache_cache
Object.const_set(:FragmentCacheCache, { acts_as_cached :store => CACHE })

# add :ttl option to caches_action on the per action level by passing in a hash instead of an array
# Examples:
# caches_action :index # will use the default ttl from your memcache.yml, or 25 minutes
# caches_action :index => { :ttl => 5.minutes } # cache index action with 5 minute ttl
# caches_action :page, :feed, :index => { :ttl => 2.hours } # cache index action with 2 hours ttl, all others use default
def self.setup_rails_for_action_cache_options
::ActionController::Caching::Actions::ActionCacheFilter.class_eval do
# convert all actions into a hash keyed by action named, with a value of a ttl hash (to match other cache APIs)
def initialize(*actions, &block)
if [].respond_to?(:extract_options!)
@options = actions.extract_options!
@actions = actions.inject(@options.except(:cache_path)) do |hsh, action|
action.is_a?(Hash) ? hsh.merge(action) : hsh.merge(action => { :ttl => nil })
@actions = actions.inject({}) do |hsh, action|
action.is_a?(Hash) ? hsh.merge(action) : hsh.merge(action => { :ttl => nil })

# override to skip caching/rendering on evaluated if option
def before(controller)
return unless @actions.include?(controller.action_name.intern)

# maintaining edge and 1.2.x compatibility with this branch
# Jan Prill - added && false
#if @options && false
# DSS - removed false - false causing else to always run - this may be
# because Jan was using Rails 1.2...
if @options
action_cache_path =, path_options_for(controller, @options))
action_cache_path =

# should probably be like ActiveRecord::Validations.evaluate_condition. color me lazy.
if conditional = @actions[controller.action_name.intern][:if]
conditional = conditional.respond_to?(:call) ? : controller.send(conditional)
# Jan Prill - causing caching to stop after a period of time?
#@actions.delete(controller.action_name.intern) if conditional == false

# Jan Prill - added if clause
cache = controller.read_fragment(action_cache_path.path) if conditional != false
if cache && (conditional || conditional.nil?)
controller.rendered_action_cache = true
if method(:set_content_type!).arity == 2
set_content_type!(controller, action_cache_path.extension)
controller.send(:render, :text => cache)
# 1.2.x compatibility
# Jan Prill added &&
controller.action_cache_path = action_cache_path if (controller.respond_to?(:action_cache_path) && conditional != false)

# override to pass along the ttl hash
def after(controller)
# Jan Prill - added || controller.action_cache_path.nil?
return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache || controller.action_cache_path.nil?
# 1.2.x compatibility
path = controller.respond_to?(:action_cache_path) ? controller.action_cache_path.path : ActionController::Caching::Actions::ActionCachePath.path_for(controller)
controller.write_fragment(path, controller.response.body, action_ttl(controller))

def action_ttl(controller)

module Extensions
def read(*args)
return if ActsAsCached.config[:skip_gets]
FragmentCacheCache.cache_store(:get, args.first)

def write(name, content, options = {})
ttl = (options.is_a?(Hash) ? options[:ttl] : nil) || ActsAsCached.config[:ttl] || 25.minutes
FragmentCacheCache.cache_store(:set, name, content, ttl)

module DisabledExtensions
def read(*args) nil end
def write(*args) "" end

Tuesday, May 20, 2008


I've been wanting to play with git, so I created repositories for all my jquery plugins at

For now, that would be:


git documentation:

Tuesday, May 6, 2008

ASP.NET - Import and display Excel spreadsheet

I needed to upload and parse an Excel spreadsheet and display it in a GridView. For the most part, pretty straight forward. I ran into an issue "Could not find installable ISAM" once I added "IMEX=1" to my connection string. This was solved by adding (char)34 as shown in my working example:

string filePath = "~/somedirectory/somespreadsheet.xls";

string strConn = @"Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source=" + MapPath(filePath) + ";"
+ "Extended Properties=" + (char)34
+ "Excel 8.0;IMEX=1;" + (char)34;

DataSet dsRecords = new DataSet();
// "Sheet" is name of sheet being opened, must add $ after the name
OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", strConn);

//da.TableMappings.Add("Table", "ExcelText");
scheduleGridView.DataSource = dsRecords.Tables[0].DefaultView;

As a note, you can also access the spreadsheet directly using the file path:
string strConn = @"Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source=c:/somedirectory/somespreadsheet.xls;"
+ "Extended Properties=Excel 8.0;";

Saturday, April 26, 2008

will_paginate gem

While upgrading an old project to Rails 2.0.2 (and having trouble getting the will_paginate plugin to install), I discovered that there is a will_paginate gem:

Railscasts - will_paginate

Thursday, April 24, 2008

Rails - ActionController::InvalidAuthenticityToken

ActionController::InvalidAuthenticityToken in User#login

Showing user/login.html.erb where line #2 raised:

No :secret given to the #protect_from_forgery call.
Set that or use a session store capable of generating its
own keys (Cookie Session Store).

This happened after I switched from using the file system to a database for storing sessions (after uncommenting the line "config.action_controller.session_store = :active_record_store" in config/environment.rb).

Once you switch to database store, you'll need to comment the "protect_from_forgery" line in app/controllers/application.rb

# See ActionController::RequestForgeryProtection for details
# Uncomment the :secret if you're not using the cookie session store
#protect_from_forgery # :secret => 'b3e36f40312f075ea2697fb85180e312'

Rails 2.0.2 - setup with functional tests

If you want to use setup with functional tests in Rails 2.0.2, you'll need to rename the setup method to setup_with_fixtures and call super before running your setup code:
def setup_with_fixtures
# Set up code here

Sunday, March 23, 2008

Ruby on Rails - Using External Asset Hosts

Rails uses the "public" directory on the current host as the default location for static assets (images, CSS, Javascript, etc). Setting up your Rails app to use an external assets server is as simple as adding a single line to a configuration file.

Add the following line to your config/environment.rb file:

ActionController::Base.asset_host = ''

It's also possible to set a single environment to use an external asset host:

Add the following line to config/environments/production.rb (the most likely spot - this line should already be in this file, but commented out):

config.action_controller.asset_host = ''

Now this line in my layout

<%= stylesheet_link_tag 'scaffold/base' %>

will translate to

Additional information on setting up multiple asset hosts can be found at:

Wednesday, March 12, 2008

Ruby Gem - Highline

I was looking for a way to prompt a user for input on the console and ran across the RubyGem HighLine. It does a lot more than this, but here's how to capture STDIN from the console:

require 'rubygems'
require 'highline/import'

username = ask("Enter your username: ") { |q| q.echo = true }
password = ask("Enter your password: ") { |q| q.echo = "*" }

Here's the output on the console:

$ ruby highline.rb
Enter your username: doug
Enter your password: ******

Get it here:


or simply install the gem the normal way:

$ sudo gem install highline

Autotesting Javascript in Rails

From Dr. Nic's Blog:

Autotesting Javascript in Rails

Installing Ruby without openssl

When installing Ruby on an old machine, I got this error:

ruby make[1]: *** [ossl_ssl.o] Error 1

Other than installing openssl, which wasn't option, install ruby without openssl:

$ ./configure prefix=/home/doug/bin/ruby --without-openssl

Monday, March 10, 2008

Javascript - insertAfter(), formatCurrency, DOM Scripting


function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode;
if (parent.lastChild == targetElement) {
} else {


function formatCurrency(amount) {
var i = parseFloat(amount);
if(isNaN(i)) { i = 0.00; }
var minus = '';
if(i < 0) { minus = '-'; }
i = Math.abs(i);
i = parseInt((i + .005) * 100);
i = i / 100;
s = new String(i);
if(s.indexOf('.') < 0) { s += '.00'; }
if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
s = minus + s;
return s;

DOM scripting - create text node with value of &nbsp;

var textEl = document.createTextNode('\u00a0');

Accordion Effects with Scriptaculous

I had a couple recent projects that required an accordion effect. I normally use jQuery, but found a couple nice Prototype/Scriptaculous accordions (one is for a Rails project, so we're already using Scriptaculous).

stickman labs

Note - The stickman labs accordion doesn't appear to work with the latest Prototype (1.6.1). I'm using the combined js file from the stickman site.

Wednesday, February 27, 2008

jQuery Sortable with Ajax, PHP, and MySQL

I needed to create a sortable list that would save the order position of data items. I've been using jQuery more and more and decided to go with the Interface Elements for jQuery.

I found a blog entry titled jQuery Sortable Ajax PHP Integration that was a good start. However, it didn't actually use MySQL to store the sorted data so I've gone ahead and added the database queries and updates.

First I created a simple table to store links (I'd like my client to order the links they enter through an admin interface).

id int(10) NOT NULL auto_increment,
link_url varchar(50) NOT NULL,
link_text varchar(50) NOT NULL,
order_position int(2),
primary key(id)

Next is the PHP page that reads the link data from the table and displays the links based on the order_position column of the table.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<script type="text/javascript" src="/js/jquery/jquery-1.2.3.min.js"></script>
<script type="text/javascript" src="interface.js"></script>

function() {
accept : 'sortitem',
onchange : function (sorted) {
serial = $.SortSerialize('sortme');

url: "sortdata.php",
type: "POST",
data: serial.hash,
// complete: function(){},
//success: function(feedback){ $('#data').html(feedback); }
// error: function(){}


<ul id="sortme">
// Connect to the database as necessary
$dbh = mysql_connect('','username','password')
or die ("Unaable to connnect to MySQL");

$selected = mysql_select_db("sort_test",$dbh)
or die("Could not select sort_test");

$result = mysql_query('SELECT * FROM links ORDER BY order_position');
while ($row = mysql_fetch_array($result)) {
print '<li id="' . $row{'id'} . '" class="sortitem">' . $row{'link_text'} . "\n";


This will make an Ajax call back to the server where PHP will update the database as you drag and sort the list data:



$sortme = $_POST['sortme'];
// Connect to the database as necessary
$dbh = mysql_connect('','username','password')
or die ("Unaable to connnect to MySQL");

$selected = mysql_select_db("sort_test",$dbh)
or die("Could not select sort_test");

for ($i = 0; $i < count($sortme); $i++) {
mysql_query("UPDATE links SET order_position=$i WHERE id=$sortme[$i]");

A little CSS certainly wouldn't hurt things. Here's some I found on another tutorial:

ul {
list-style: none;
li {
background: #727EA3;
color: #FFF;
width: 100px;
margin: 5px;
font-size: 10px;
font-family: Arial;
padding: 3px;

I wouldn't call this production ready code, but all the pieces are in place if you'd like to use jQuery with Ajax, PHP, and MySQL for a sortable list. Don't forget, you'll need to get jQuery itself and the interface.js file as well. Another thing to consider is alerting the user if the update fails or takes a long time.

Thursday, February 21, 2008

Ruby on Rails - Testing with Multiple Databases

I ran into errors when running tests for a Rails app using multiple databases. When testing, fixtures are automatically inserted into the primary database, and I was getting an error on an unused default fixture that was created when I built the model tied to the second database. Removing that fixture got my tests to pass...

More info here:

and on multiple databases in general:

Tuesday, February 19, 2008


I've been using the jQuery Javascript library a lot lately and it's definitely become my favorite library. (I've written four plugins in the last couple months to boot)

Here are a few links to useful jQuery resources.

jQuery: The Write Less, Do More, JavaScript Library
jQuery UI: Widgets, Components, and Interaction
Plugins - jQuery JavaScript Library
jQuery Blog
Learning jQuery
Visual jQuery
IBM developerWorks: Simplify Ajax development with jQuery


Ruby on Rails does not support composite primary keys and a legacy database I'm working with has lots of them...after a quick search I found this useful Gem:


Wednesday, January 23, 2008

10 Ruby on Rails Plugins You Should Be Using

Media72: 10 Ruby on Rails Plugins You Should Be Using

jQuery: Cookie Plugin

I've become a big fan of jQuery and have contributed two small plugins myself, so when it came time to switch to a library for cookie manipulation with Javascript (time to replace all that nasty inline JS code) my first choice was jQuery.

Not to be disappointed, I found that Klaus Hartl has written a very slim and useful Cookie Plugin for jQuery.

Here's a small page test using the jQuery Cookie plugin:

<title>jquery cookie</title>

<script type="text/javascript" src="jquery-1.2.1.min.js"></script>
<script type="text/javascript" src="jquery.cookie.js"></script>

<script type="text/javascript">

$(function($) {

function displayMessage(msg) {
$('#message').html(msg).css({color: 'green'});

displayMessage('jQuery cookie plugin test');

$('#setSessionCookie').click(function() {
$.cookie('test', 'Hmmm, cookie');
displayMessage("Cookie 'test' has been set.");

$('#setCookie').click(function() {
$.cookie('test', 'Hmmm, cookie', { expires: 7 });
displayMessage("Cookie 'test' has been set and will expire in 7 days.");

$('#getCookie').click(function() {
displayMessage("The value of the cookie named 'test' is: " + $.cookie('test'));

$('#deleteCookie').click(function() {
$.cookie('test', null);
displayMessage("Cookie 'test' has been deleted.");

$('#testCookiesEnabled').click(function() {
$.cookie('testcookiesenabled', null);
$.cookie('testcookiesenabled', 'enabled');
if ($.cookie('testcookiesenabled')) {
displayMessage("Cookie: "+ $.cookie('testcookiesenabled'));
} else {
displayMessage("Cookies disabled");
$.cookie('testcookiesenabled', null);





<p><span id="message" style="forecolor: red;"></span>

<p><input type="button" id="testCookiesEnabled" value="Cookies enabled?"/></p>

<p><input type="button" id="setSessionCookie" value="Set session cookie"/></p>

<p><input type="button" id="setCookie" value="Set cookie expires in 7 days"/></p>

<p><input type="button" id="getCookie" value="Show cookie value"/></p>

<p><input type="button" id="deleteCookie" value="Delete the cookie"/></p>


My jQuery cookie demo using jquery.cookie.js

Monday, January 21, 2008

ASP.NET GridView - Header always bold

GridView uses a table and creates a <th> tag for the header, which will bold all the text generated by the GridView. Here's a simple solution:

Set a style:

.GridViewHeaderStyle th {
font-weight: normal;

And apply it to your GridView:

<asp:GridView ID="grdSomeGrid" runat="server" CssClass="GridViewHeaderStyle">

Saturday, January 19, 2008

ASP.NET GridView "ShowFooter"

Sometimes it's the small things that get you...

Uh, not that it ever happened to me, but in case you can't get your GridView template footer to show up...don't forget 'ShowFoooter="true"' :)

<asp:GridView ID="grdListings" runat="server" AutoGenerateColumns="false" BorderWidth="0"
AllowPaging="true" PageSize="5" OnPageIndexChanging="grdListings_PageIndexChanging" ShowFooter="true">






Saturday, January 5, 2008

Install Ruby without openssl

When installing Ruby on an old machine, I got this error:

ruby make[1]: *** [ossl_ssl.o] Error 1

Other than installing openssl, which wasn't option, install ruby without openssl:

$ ./configure prefix=/home/doug/bin/ruby --without-openssl

Autotesting Javascript in Rails

From Dr. Nic's Blog:

Autotesting Javascript in Rails

Thursday, January 3, 2008

Upgrading to specific version of Rails

sudo gem install -v=2.0.1 rails --include-dependencies

About Me

My photo
Developer (Ruby on Rails, iOS), musician/composer, Buddhist, HSP, Vegan, Aspie.

Blog Archive