<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4293464655956680856</id><updated>2012-01-24T11:21:23.557-08:00</updated><category term='ruby'/><category term='remote control'/><category term='selenium'/><category term='aliases bash growl growlnotify'/><category term='selenium plugin remote control rails'/><category term='textmate regular expression'/><category term='rails'/><title type='text'>Steve's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-8407478259569193842</id><published>2008-05-20T03:03:00.000-07:00</published><updated>2008-05-20T03:05:39.991-07:00</updated><title type='text'>New blog</title><content type='html'>I'm ditching blogspot and using my own install of Radiant at &lt;a href="www.iannopollo.com"&gt;iannopollo.com&lt;/a&gt;. Check it out&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;window.location = "http://www.iannopollo.com"&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-8407478259569193842?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/8407478259569193842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=8407478259569193842' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/8407478259569193842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/8407478259569193842'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2008/05/new-blog.html' title='New blog'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-1980831231231194517</id><published>2008-02-17T14:24:00.000-08:00</published><updated>2008-02-17T14:52:17.707-08:00</updated><title type='text'>Mail Fetcher - Fetch Email from Ruby and Rails</title><content type='html'>I recently had to write something to fetch emails from a GMail account and process the emails to check if the email was a bounce (bad email address). If so, the person in the system associated with the bounced email would be deleted from the database. I did some searching for such thing and found this:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wiki.rubyonrails.org/rails/pages/HowToReceiveEmailsWithActionMailer"&gt;How to receive emails with Rails&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;About half way down the page you see an example for polling emails from a POP3 server (edited for space):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;require 'net/pop'&lt;br /&gt;require File.dirname(__FILE__) + '/../config/environment'&lt;br /&gt;&lt;br /&gt;logger = RAILS_DEFAULT_LOGGER&lt;br /&gt;&lt;br /&gt;logger.info "Running Mail Importer..." &lt;br /&gt;Net::POP3.start("mail.server.net", nil, "username", "password") do |pop|&lt;br /&gt;  if pop.mails.empty?&lt;br /&gt;    logger.info "NO MAIL" &lt;br /&gt;  else&lt;br /&gt;    pop.mails.each do |email|&lt;br /&gt;&lt;br /&gt;      begin&lt;br /&gt;        logger.info "receiving mail..." &lt;br /&gt;        Mailman.receive(TMail::Mail.parse(email.pop))&lt;br /&gt;        email.delete&lt;br /&gt;      rescue Exception =&gt; e&lt;br /&gt;        logger.error e.message&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;logger.info "Finished Mail Importer."&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So try this with a GMail server and you get no connection. Why? Because Google uses SSL when logging in via POP3. So the I looked around and found someone using SSL to login via POP3. All they did was add this line right before trying to start the connection: &lt;tt&gt;Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_NONE)&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Simple enough. I went ahead and tried that, and it blows up with the following error: &lt;tt&gt;undefined method `enable_ssl' for Net::POP3:Class&lt;/tt&gt;. Now trying to find out why this didn't work was annoying, but I finally found out that in the current version of Ruby (1.8.6), Net::POP3 doesn't understand enable_ssl. The edge version, however, does. So, I got the net/pop.rb file and required it instead of the 1.8.6 version and voila! It works! So, instead of just posting this and letting everyone know that you have to do this to make SSL POP3 access work, I made a plugin:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mail-fetcher.rubyforge.org/svn/trunk/"&gt;Mail Fetcher&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now the whole world may enjoy SSL POP3 access to their hearts' content. And, it also works with IMAP. Checkout the README and mail_fetcher.rb to get all the details. Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-1980831231231194517?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/1980831231231194517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=1980831231231194517' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/1980831231231194517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/1980831231231194517'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2008/02/mail-fetcher-fetch-email-from-ruby-and.html' title='Mail Fetcher - Fetch Email from Ruby and Rails'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-3948691806241242703</id><published>2008-02-11T13:12:00.000-08:00</published><updated>2008-02-17T15:40:18.895-08:00</updated><title type='text'>Talking to Gmail with Ruby and Rails</title><content type='html'>Recently I came across a dilemma in trying to send and receive emails from a Rails app: Either install a full-blown postfix server on a Linux box (by full-blown, I mean account handling, POP/IMAP interface, anti-spam, anti-virus, etc etc), or use Google to handle all the emailing. So, me not being a Linux/sys-admin junkie, I strongly opted for the Google route (and after some persuasion the customer, thankfully, agreed :-). So I went about to find the best practices for working with Google Apps (http://www.google.com/a which is where you sign up). I came across &lt;a href="http://www.danielfischer.com/2008/01/09/how-to-use-gmail-as-your-mail-server-for-rails/"&gt;this very helpful post&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You just install the mentioned plugin, create the appropriate mailer.yml file and you're good to go. ActionMailer will login as the specified account and send emails through that account. Genius! &lt;br /&gt;&lt;br /&gt;On a side note, I was able to get a Rails app to talk (no sending though, just receiving) to gmail by using the new net/pop library in the latest ruby and making the &lt;a href="http://siannopollo.blogspot.com/2008/02/mail-fetcher-fetch-email-from-ruby-and.html"&gt;Mail Fetcher plugin&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But back to the main point, being able to send through the Google Apps account. The technical stuff seems really easy now. Just send your emails out like normal and have some way to check responses either manually or programmatically like I showed above. You're golden, or so it seems. &lt;br /&gt;&lt;br /&gt;If you have an application like the one I'm working on, you have many emails being sent for single actions (one to the person who submitted a form, and then 10 - 100 emails being sent to others notifying them of the form submission as well). That seems fine up until you read through the Google Apps help center and find out that you can &lt;a href="http://www.google.com/support/a/bin/answer.py?answer=59797"&gt;only send emails&lt;/a&gt; to 500 addresses each day per account (so either 1 email message with 500 recipients, or 500 emails each with one recipient). &lt;br /&gt;&lt;br /&gt;If you have a commercial application, that is a serious limitation, and one that might stop you from using Google as your email hosting solution.&lt;br /&gt;&lt;br /&gt;The important thing to note though is that the limitation is on &lt;i&gt;one account&lt;/i&gt; per day. With Google Apps, you receive your Google Apps account which allows you to administer certain things like a calendar, file uploads (which at this point is pretty lame), chatting, and email. Google allows you to create users who can use these features in your domain. So you can create john@mydomain.com and mildred@mydomain.com, and they can have an email account, read your files, chat with each other, and check the mydomain.com calendar. The accounts that get limited are the accounts you create, not your Google App account. There is hope! Google allows you to create quite a few accounts for your domain (200 when you sign up, and you can always &lt;a href="http://rubyurl.com/L0Pd"&gt;ask for more&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;What that means is that you are not limited to 500 emails per day, but really 100,000 emails per day (200 * 500). That's a lot of traffic! The obvious way to use all of it is to create a bunch of accounts (don't forget to enable either POP3 or IMAP access!) and randomly send from them all. Just set up account names like "system1@example.com" and "system2@example.com" and randomly choose which one to send from each time you send out an email. It just works, and it distributes the load of sent emails pretty well across all email accounts. Implementation wise, &lt;a href="http://pastie.caboo.se/153510"&gt;I did something like this&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;It ends up sending from email addresses "system100@example.com" through "system110@example.com". Also, in that example I put in the ActionMailer::Base.smpt_settings for clarity, but in reality I have them in the config/mailer.yml file used by the action_mailer_tls plugin.&lt;br /&gt;&lt;br /&gt;Hopefully this will help someone who is on the fence about using Google Apps as a solution to email after finding out about the sending limit. Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-3948691806241242703?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/3948691806241242703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=3948691806241242703' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/3948691806241242703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/3948691806241242703'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2008/02/talking-to-gmail-with-ruby-and-rails.html' title='Talking to Gmail with Ruby and Rails'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-9058281131540161312</id><published>2007-11-03T14:03:00.000-07:00</published><updated>2007-11-03T15:23:32.386-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='aliases bash growl growlnotify'/><title type='text'>bash aliases</title><content type='html'>Bash aliases are such lovely things, so I thought I would share some of my favorites and maybe even get some feedback. &lt;br /&gt;&lt;br /&gt;Most of my aliases are there to make software development more enjoyable and less time consuming. As such, most of them deal with the projects I have in my project directories. Here are some of the more interesting ones:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;for bigdir in $(ls ~/Developer/Projects/ | cut -d' ' -f7)&lt;br /&gt;do &lt;br /&gt;  for dir in $(ls ~/Developer/Projects/$bigdir)&lt;br /&gt;    do&lt;br /&gt;      alias cd$dir="cd ~/Developer/Projects/$bigdir/$dir"&lt;br /&gt;      alias m$dir="cd$dir &amp;&amp; mate ."&lt;br /&gt;      alias s$dir="cd$dir &amp;&amp; ss"&lt;br /&gt;      alias g$dir="~/bin/svngrowl $dir"&lt;br /&gt;      alias o$dir="osascript -e 'tell application \"Terminal\"'&lt;br /&gt;        -e 'tell application \"System Events\"'&lt;br /&gt;        -e 'tell process \"Terminal\" to keystroke \"t\" using command down'&lt;br /&gt;        -e 'tell process \"Terminal\" to keystroke \"t\" using command down'&lt;br /&gt;        -e 'end tell'&lt;br /&gt;        -e 'do script \"s$dir\" in first tab of front window'&lt;br /&gt;        -e 'do script \"m$dir\" in second tab of front window'&lt;br /&gt;        -e 'do script \"g$dir\" in third tab of front window'&lt;br /&gt;        -e 'do script \"localhost\" in second tab of front window'&lt;br /&gt;        -e 'tell second tab of front window to set selected to true'&lt;br /&gt;        -e 'end tell'"&lt;br /&gt;    done&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;alias localhost="open http://localhost:3000"&lt;br /&gt;alias addall="svn st | grep ? | cut -d' ' -f7 | xargs svn add"&lt;br /&gt;alias removeall="svn st | grep ? | cut -d' ' -f7 | xargs rm -Rf"&lt;br /&gt;&lt;br /&gt;for var in "server" "generate" "console" "destroy" "plugin"&lt;br /&gt;do&lt;br /&gt;  alias s${var:0:1}="script/$var"&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The first for loop is probably the most useful set of aliases that I have. It starts off by going through all the projects that live in my various project directories. Then, for each project it gives me a cdproject, mproject, sproject, gproject (very special), and oproject (less special, but still useful).&lt;br /&gt;&lt;br /&gt;cdproject&lt;br /&gt;&lt;ul&gt;&lt;li&gt;cd's into the project directory&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;mproject&lt;br /&gt;&lt;ul&gt;&lt;li&gt;opens the project in TextMate&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;sproject&lt;br /&gt;&lt;ul&gt;&lt;li&gt;starts a server for the project by calling script/server (which is what the alias ss does in a rails project)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;gproject&lt;br /&gt;&lt;ul&gt;&lt;li&gt;starts an svngrowl process for the project (which I'll explain later)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;oproject&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Uses the command line osascript, which invokes applescript, to manipulate Terminal and Firefox&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;First, an explanation of what oproject is doing. To start, for viewing purposes above I cut the oproject alias into more manageable pieces, but when used should be on one line (as would be the case if it were called from the command line).&lt;br /&gt;&lt;br /&gt;This alias is kind of like the Ring of Power, in that it rules all the other aliases, and in the darkness (or the light) binds them... into one convenient call. It opens Terminal, and opens 2 new tabs for a total of 3 tabs (only for Leopard users though :-). It then opens a server in the first tab, opens the project in TextMate in the second tab, starts an svngrowl process in the third tab, goes back to the second tab and runs the alias localhost, and then gives focus back to the second tab (since it seemed to lose focus to the third tab, not sure why). This alias is a huge time saver when you think that every working day I spend about 10 to 15 seconds when I have to open everything up (which adds up to a lot when you have enough work to do!).&lt;br /&gt;&lt;br /&gt;As for the gproject alias, this uses a cool little script in my ~/bin directory that starts a loop for the specified project, and every 3 minutes it runs svn up on the project and if there are any changes to the project, it sends out a pretty little growl notification with what was changed, who changed it, the commit message, and if any migrations were committed it changes the priority of the message to high (which for my personal growl settings turns the message text red). &lt;br /&gt;&lt;br /&gt;Two scripts are involved in the growling, one bash script, and a ruby script (which is invoked by the bash script). First, the bash script (cut in half for easy viewing):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;source ~/.profile&lt;br /&gt;alias | grep cd$@= | awk "{gsub(/cd$@='cd |'/, \"\"); print}" |&lt;br /&gt;awk "{gsub(/~/, \"/Users/`whoami`\"); print}" | xargs ~/bin/svngrowl.rb&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;And now the ruby script:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/env ruby&lt;br /&gt;begin&lt;br /&gt;  directory = ARGV[0]&lt;br /&gt;  project = directory.split("/").last&lt;br /&gt;  ignore = directory.gsub(project, "")&lt;br /&gt;&lt;br /&gt;  loop do&lt;br /&gt;    updates = `svn up #{directory}`.gsub(ignore, "").split("\n")&lt;br /&gt;    last_log = `svn log #{directory} --limit 1`&lt;br /&gt;  &lt;br /&gt;    revision = updates.pop.scan(/\d+/)&lt;br /&gt;    committer = last_log.split("\n")[1].split(" | ")[1]&lt;br /&gt;    priority = updates.join("\n").include?("db/migrate") ? 1 : 0&lt;br /&gt;    message = last_log.split("\n")[2..-2].join("\n")&lt;br /&gt;  &lt;br /&gt;    unless updates.empty?&lt;br /&gt;      `growlnotify -s -t "#{project} Update - #{committer}"&lt;br /&gt;      -m "#{message + "\n\n" + updates.join("\n")}" -p #{priority} --image ~/bin/mph.png`&lt;br /&gt;    end&lt;br /&gt;    sleep 180&lt;br /&gt;  end&lt;br /&gt;rescue&lt;br /&gt;  `~/bin/svngrowl.rb #{directory}`&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;All the bash script does is finds the proper directory for the project in question and passes it to the ruby script. The ruby script in turn does an svn up on the directory, collects all the interesting data, and runs growlnotify (the command line growl utility) displaying all of the interesting data. There is also a rescue statement in there that just restarts the process if something goes wrong (an error is thrown if svn can't update properly, which can happen if the network drops out or if you do svn st at the same time that this process is doing svn up). I also used the --image options to pass in a beautiful picture of Mr. Potato Head to use as the icon shown on the notification.&lt;br /&gt;&lt;br /&gt;Please feel free to use any of these to make your work/play more productive (except for the picture of Mr. Potato Head... that one is mine!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-9058281131540161312?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/9058281131540161312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=9058281131540161312' title='45 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/9058281131540161312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/9058281131540161312'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2007/11/bash-aliases.html' title='bash aliases'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>45</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-2601380775891104822</id><published>2007-10-02T03:00:00.000-07:00</published><updated>2007-10-02T03:20:30.549-07:00</updated><title type='text'>sfight!</title><content type='html'>I played around yesterday when I got bored and wrote a little script which pits developers on a project against each other to see who has the most subversion commits. It doesn't really mean too much who wins since you can have plenty of little commits that fix things, but it is just fun to do to see who wins! This script assumes the developers on the project have separate subversion logins. Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/env ruby&lt;br /&gt;developers = ARGV.select {|arg| !arg.empty? &amp;&amp; !arg.nil?}&lt;br /&gt;raise "You need two developers to fight" if developers.size &lt; 2&lt;br /&gt;&lt;br /&gt;log = `svn log`&lt;br /&gt;separator = log.scan(/^-.*?-$/).first&lt;br /&gt;log_entries = log.split(separator)[1..-2]&lt;br /&gt;names = log_entries.collect {|entry| entry.split(" | ")[1]}&lt;br /&gt;&lt;br /&gt;numbers = developers.collect {|developer| names.select {|entry| entry == developer}.size}&lt;br /&gt;&lt;br /&gt;results = []&lt;br /&gt;developers.each_with_index {|developer, i| results &lt;&lt; "#{numbers[i].to_s.ljust(3)}- #{developer}"}&lt;br /&gt;&lt;br /&gt;puts results.sort {|x, y| y.scan(/\d+/).first.to_i &lt;=&gt; x.scan(/\d+/).first.to_i}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Use it like this (assuming you chmod'ed it to be executable, and put it into your ./script directory):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;./script/sfight developer1 developer2 developer3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;style type='text/css'&gt;&lt;!--#sidebar-wrapper {width:130px !important}#main-wrapper {width:650px !important}#outer-wrapper {width:800px !important}--&gt;&lt;/style&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-2601380775891104822?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/2601380775891104822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=2601380775891104822' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/2601380775891104822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/2601380775891104822'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2007/10/sfight.html' title='sfight!'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-8581109622305504423</id><published>2007-08-28T16:33:00.000-07:00</published><updated>2007-08-28T17:07:38.506-07:00</updated><title type='text'>Rails and SSL (https://)</title><content type='html'>So I recently had to have some secure routes for a site I am currently working on. If you are using deprec and deploying to a slicehost, getting the SSL certificate stuff working is a snap. If you want your whole site to be over SSL, then all you do is put in a permanent redirect to socket 443 in your app_name.conf file. But, if you need to do something interesting like go back and forth between http and https, then you need to do a little digging. &lt;br /&gt;&lt;br /&gt;Doing a google search doesn't bring up anything particularly useful in terms of going back and forth between http and https, but one thing did catch my eye. In your routes you can pass a protocol option to set which protocol you are going to use (something like http, file, svn, https, etc...). I also had to dig through some code to find out how to pass that option in, since it gets set two different ways depending on what kind of route you are using. If you do a map.resource(s) route, then you have to set the option as &lt;code&gt;:requirements =&gt; {:protocol =&gt; ROUTES_PROTOCOL}&lt;/code&gt;, whereas if you just do a map.route_name type route, then you just pass in &lt;code&gt;:protocol =&gt; ROUTES_PROTOCOL&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;You should also be careful about when you are setting that protocol, as trying to access https://localhost:3000 just doesn't work (such as in development mode). I just set a conditional constant at the top of my routes file like so: &lt;code&gt;ROUTES_PROTOCOL = (ENV["RAILS_ENV"] =~ /development/ ? "http" : "https")&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Two more caveats: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;First caveat is that if you want to go back and forth between http and https, you MUST explicitly set all of your routes to have http or https protocol. If you don't, then when rails generates your routes it will just use the protocol of the current page. This is annoying, but I can see why they would do this (if you are looking at something securely, then just look at everything securely).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Second caveat is that you must use the route_name_url throughout your application instead of route_name_path, as some are accustomed to. The _url named route gives you the full url (duh), which is what you want if you are on a page using http and want to go to https (whereas _path only gives you the uri, and will use the protocol and host of the current page). If you already use _url, then you are one step ahead in the game.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Here is a sample of some of my routes using the protocol option:&lt;br /&gt;&lt;pre&gt;&lt;code style="font-size:11px !important;"&gt;&lt;br /&gt;# Public routes using http protocol&lt;br /&gt;map.with_options :protocol =&gt; "http" do |http|&lt;br /&gt;  http.login '/login',   :controller =&gt; 'sessions', :action =&gt; 'new'&lt;br /&gt;  http.logout '/logout',  :controller =&gt; 'sessions', :action =&gt; 'destroy'&lt;br /&gt;  http.resources :users, :sessions, :requirements =&gt; {:protocol =&gt; "http"}&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;# Public routes using https protocol&lt;br /&gt;map.with_options :protocol =&gt; ROUTES_PROTOCOL do |https|&lt;br /&gt;  https.form_step '/form/*slug', :controller =&gt; 'forms', :action =&gt; 'show'&lt;br /&gt;  https.form_edit '/edit/*path', :controller =&gt; 'forms', :action =&gt; 'edit'&lt;br /&gt;  https.resources :forms, :requirements =&gt; {:protocol =&gt; ROUTES_PROTOCOL}&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-8581109622305504423?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/8581109622305504423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=8581109622305504423' title='65 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/8581109622305504423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/8581109622305504423'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2007/08/rails-and-ssl-https.html' title='Rails and SSL (https://)'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>65</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-2566656565293103220</id><published>2007-05-23T17:40:00.000-07:00</published><updated>2007-05-23T17:59:41.650-07:00</updated><title type='text'>Different ways to program</title><content type='html'>I've been told that there are different ways to program. One way is procedural, where you work with something (let's say a shopping cart), and it does one thing, then it does another, then another, and so on until oblivion. Then there is object-oriented programming, where you have objects  that you deal with (like in real life!) and not just random things that you happen to write code about. So your shopping cart has attributes, like it can hold items, you can remove items from it, and when it is time to checkout you remove all of the items from the cart and pay for the items. And just like at the grocery store, you leave the cart at the store (hopefully). &lt;br /&gt;&lt;br /&gt;I guess the difference programming wise is that procedural programming you just write a whole slew of functions that can be applied anywhere and it is the programmers job to decide when and where he should use them, whereas in OOP you have classes for your objects, and each class has specific functions to deal mainly with instances (objects) of the class. I'm sure you can have the guise of OOP and still be doing procedural programming. &lt;br /&gt;&lt;br /&gt;I only mention all this because I was looking through a website that the client I am working for said to look at and try to mimic what they were doing with some javascript showing and hiding. It all boiled down to that they were toggling the CSS display property on DOM elements between "block" and "none" (the show() and hide() functions in Prototype). Well, I finally found that out after looking on in amazement at a 1211 line function that seemed to show and hide everything on the entire website! Notice that I said &lt;span style="font-style:italic;"&gt;function&lt;/span&gt;. They just used this massive catch all function to do all the showing and hiding, instead of trying to somehow abstract it into some showing/hiding class thingy (don't ask me how I would do it though, because I have no idea). Maybe I would have done it like that if I wouldn't have gone insane trying to remember exactly where I was in the 1200+ lines of code. &lt;br /&gt;&lt;br /&gt;And as a side note, look at this code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;if (getFormObject("reslease","taxes")[0].checked) {&lt;br /&gt;   setVisDisp('taxesDiv',true);&lt;br /&gt;   if (getFormObject("reslease","taxesTenant")[0].checked) {&lt;br /&gt;      setVisDisp('taxesTenantDescDiv',true);&lt;br /&gt;   } else {&lt;br /&gt;      setVisDisp('taxesTenantDescDiv',false);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   if (getFormObject("reslease","taxesGovt")[0].checked) {&lt;br /&gt;      setVisDisp('taxesGovtDescDiv',true);&lt;br /&gt;   } else {&lt;br /&gt;      setVisDisp('taxesGovtDescDiv',false);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;} else {&lt;br /&gt;   setVisDisp('taxesDiv',false);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That was from line 1070 to 1086. After almost 1100 lines of madness, how do really know that you want the first element from the "reslease" form? And what is a "taxesTenantDescDiv"? My mentor has been drilling it into my head to make whatever your coding self-descriptive, so that when you go back you never have to wonder what the "taxesTenantDescDiv" is, or where it lives.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-2566656565293103220?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/2566656565293103220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=2566656565293103220' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/2566656565293103220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/2566656565293103220'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2007/05/different-ways-to-program.html' title='Different ways to program'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-7175048553708293296</id><published>2007-04-25T04:27:00.000-07:00</published><updated>2007-04-25T04:40:53.912-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='textmate regular expression'/><title type='text'>Regular Expression Finding in TextMate</title><content type='html'>&lt;p&gt;Recently I had to convert a list of items in a word doc over to a yaml file in order so that I could load the data into our database. The word doc only contained the data necessary that a human could read and understand what was needed (meta data), but looked nothing like what the final yaml needed to look like. So I had two options, either sit there for 2 hours typing everything by hand over to yaml, or spend 20 minutes learning how to use the regular expression finding feature in TextMate. I went with the latter and am oh so glad I did. $1 is now my friend.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If you haven't tried it yet, play around with it ad see how awesome it can be!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-7175048553708293296?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/7175048553708293296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=7175048553708293296' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/7175048553708293296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/7175048553708293296'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2007/04/regular-expression-finding-in-textmate.html' title='Regular Expression Finding in TextMate'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-9015907448929298998</id><published>2007-04-15T04:01:00.000-07:00</published><updated>2008-02-17T14:56:51.649-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='selenium plugin remote control rails'/><title type='text'>Selenium Remote Control Plugin!</title><content type='html'>I recently had a need to get the selenium testing working for another app I was working on and had to copy a bunch of files and whatnot, which I knew was bad. So I took about an hour the other morning and turned it into a plugin for all the world to enjoy. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://selenium-rc.rubyforge.org/svn/trunk/"&gt;Here's the repository&lt;/a&gt;. Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-9015907448929298998?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/9015907448929298998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=9015907448929298998' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/9015907448929298998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/9015907448929298998'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2007/04/selenium-remote-control-plugin.html' title='Selenium Remote Control Plugin!'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-8414888416588213140</id><published>2007-03-14T19:18:00.000-07:00</published><updated>2007-03-14T19:45:12.075-07:00</updated><title type='text'>ActiveRecord magic</title><content type='html'>&lt;p&gt;Or so &lt;a href="http://blog.hasmanythrough.com/2006/8/13/how-dynamic-finders-work"&gt;Josh Susser&lt;/a&gt; puts it. I think it is. It's dynamic finding. I had no idea this was possible until a few days ago when i wrote some moderately-ugly looking method like: &lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def find_or_create_order&lt;br /&gt;  unless @order = Order.find(params[:blah])&lt;br /&gt;    @order = Order.create!(params[:blah])&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Then one of the geniuses (since I am working with multiple geniuses) I am working with right now came over and said "You can just use Order.find_or_create_by_blah(params[:blah])." I tried it out, and to my amazement (and I am easily amazed, and amused) it worked! I could try to explain it, but I think Josh Susser has a far greater understanding of how it works, so just go read his post if you're interested.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I did however do some playing, and found some really cool things you can do with these finders. Let's say you have an ActiveRecord model named Order. Let's also say that Order has 7 attributes on it, each labeled "1" through "7". You can write a massive line of code to find or create an Order as follows: &lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Order.find_or_create_by_1_and_2_and_3_and_4_and_5_and_6&lt;br /&gt;_and_7("1", "2", "3", "4", "5", "6", "7")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The possibilities are &lt;b&gt;endless&lt;/b&gt;!!!! Or so I imagine. One easy way to find out is to make an ActiveRecord model with 50 attributes and try to find_or_create one using the above method :-) I'm sure there are more sophisticated ways of using this, but just think of the shock value when you show this to a competent programmer. Their jaw will drop, and they'll say something like "You're smoking crack, man!"&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-8414888416588213140?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/8414888416588213140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=8414888416588213140' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/8414888416588213140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/8414888416588213140'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2007/03/activerecord-magic.html' title='ActiveRecord &lt;i&gt;magic&lt;/i&gt;'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4293464655956680856.post-8734927482935919585</id><published>2007-02-14T19:27:00.000-08:00</published><updated>2007-02-18T04:51:09.761-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='selenium'/><category scheme='http://www.blogger.com/atom/ns#' term='remote control'/><title type='text'>Selenium and Ruby: They actually work together!</title><content type='html'>So we found out this week. Just wanted to do a brain-dump so I could remember how to configure the Selenium Remote Control to work with Ruby on Rails, and hopefully impart knowledge to those who wish to play with Selenium. &lt;br /&gt;&lt;br /&gt;For a refresher, Selenium is a testing framework that allows you to test the clicking-around aspect of your web application. It allows you to record clicks and all sorts of actions that you may routinely perform to test whether you have broken something in your web application after changing some code. I recently started using this week after having some major changes in a application that I am working on with a friend. &lt;br /&gt;&lt;br /&gt;A major portion of code was changed from being mostly server-side code (with a ton of SQL calls) to client side (using JavaScript). This threw a wrench into our testing of the application because we could no longer test the actions that one might perform on the screen because there were very few calls being made to the server through Rails (it was all being done with JavaScript in the browser). So to test this we decided to go with the most excellent program Selenium. The following is a somewhat detailed overview of how to get Selenium tests working with Ruby and Rails, and by that I mean being able to write your Selenium tests with Ruby code:&lt;br /&gt;  &lt;ul&gt;&lt;br /&gt;   &lt;li&gt;Get &lt;a href="https://addons.mozilla.org/firefox/2079/"&gt;Selenium IDE&lt;/a&gt; (the Firefox extension).&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Download the &lt;a href="http://www.openqa.org/selenium-rc/download.action"&gt;Selenium Remote Control&lt;/a&gt; and stick the unzipped folder into the &lt;tt&gt;lib&lt;/tt&gt; directory of your application; you may wish to delete all the extraneous garbage, since all you will need is the ruby folder and the server folder. Also, in your &lt;tt&gt;lib&lt;/tt&gt; directory make a file named &lt;tt&gt;selenium.rb&lt;/tt&gt;, and the only thing needed in the file is &lt;tt&gt;require "selenium/ruby/selenium-ruby"&lt;/tt&gt;. You will see why later.&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Start a test server (&lt;tt&gt;script/server -e test --port 3001&lt;/tt&gt;) for selenium to work with so it doesn't try to use your development db. Choosing the port number is optional, but you will need to know which port this server is running on to use in your test file.&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Start a java server (make sure you have &lt;a href="http://java.sun.com/javase/downloads/index.jsp"&gt;JRE 1.5 or higher&lt;/a&gt;) by navigating to the &lt;tt&gt;selenium/server&lt;/tt&gt; folder in your &lt;tt&gt;lib&lt;/tt&gt; directory on a command line and type &lt;tt&gt;java -jar selenium-server.jar&lt;/tt&gt;. This will start a Jetty server on port 4444.&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Make a folder in your test directory named &lt;tt&gt;selenium&lt;/tt&gt;. This is where you will put your selenium tests when you make them.&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;Save some recorded tests from the Selenium IDE in your &lt;tt&gt;test/selenium&lt;/tt&gt; folder. You will need to perform the test in the IDE and then export the tests as "Ruby - Selenium RC". This will package the normal table tests into some handy Ruby code. You will need to rename the test class to be a proper name (something like MyNewSeleniumTest) and also whack the &lt;tt&gt;require 'test/unit'&lt;/tt&gt; and replace it with &lt;tt&gt;require File.dirname(__FILE__) + '/../test_helper'&lt;/tt&gt;.&lt;/li&gt; &lt;br /&gt; &lt;/ul&gt;&lt;br /&gt;Your selenium test should look something like the following, and should follow the normal Rails test-naming conventions "my_new_test.rb":&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;require File.dirname(__FILE__) + '/../test_helper'&lt;br /&gt;require "selenium"&lt;br /&gt;&lt;br /&gt;class MyNewSeleniumTest &lt; Test::Unit::TestCase&lt;br /&gt;  def setup&lt;br /&gt;    @verification_errors = []&lt;br /&gt;    if $selenium&lt;br /&gt;      @selenium = $selenium&lt;br /&gt;    else&lt;br /&gt;      @selenium = Selenium::SeleneseInterpreter.new("localhost", &lt;br /&gt;        4444, "*firefox", "http://localhost:3001", 10000);&lt;br /&gt;      @selenium.start&lt;br /&gt;    end&lt;br /&gt;    @selenium.set_context("test_new", "info")&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def teardown&lt;br /&gt;    @selenium.stop unless $selenium&lt;br /&gt;    assert_equal [], @verification_errors&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def test_new&lt;br /&gt;    @selenium.open "/"&lt;br /&gt;    @selenium.type "b-query", "hey yo"&lt;br /&gt;    @selenium.click "b-searchbtn"&lt;br /&gt;    @selenium.wait_for_page_to_load "30000"&lt;br /&gt;    @selenium.click "link=Privacy Policy"&lt;br /&gt;    @selenium.wait_for_page_to_load "30000"&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The line &lt;tt&gt;require "selenium"&lt;/tt&gt; will call the &lt;tt&gt;selenium.rb&lt;/tt&gt; file in your &lt;tt&gt;lib&lt;/tt&gt; folder, which calls the &lt;tt&gt;selenium-ruby.rb&lt;/tt&gt; file. This nice trick avoids having to load and use the selenium gem. You can, however, download the gem if you wish (&lt;tt&gt;gem install selenium&lt;/tt&gt;) and kill the &lt;tt&gt;selenium.rb&lt;/tt&gt; in your &lt;tt&gt;lib&lt;/tt&gt; folder, and everything will still work properly.&lt;br /&gt;&lt;br /&gt;Pay close attention to this line in the setup method: &lt;tt&gt;@selenium = Selenium::SeleneseInterpreter.new("localhost", 4444, "*firefox", "http://localhost:3001", 10000)&lt;/tt&gt;. The &lt;tt&gt;"http://localhost:3001"&lt;/tt&gt; should be the port that your test server is running on. We banged our heads against a wall for quite a while until we figured that out. You can also choose Firefox or (::dread::) IE as the browser that Seleium will open. Mac users may want Safari, but we haven't checked to see about any surprises with Safari and Selenium. &lt;br /&gt;&lt;br /&gt;That should be all you need (not that much, right?). Now you can run your tests from the command line like you would any other individual test (in Win-doze: &lt;tt&gt;ruby test\selenium\new_selenium_test&lt;/tt&gt;). You can set up a rake task (to go into your &lt;tt&gt;lib/tasks&lt;/tt&gt; folder) to run all of your tests for you pretty easily, like the following one we set up:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;namespace :test do&lt;br /&gt;  Rake::TestTask.new(:selenium =&gt; "db:test:prepare") do |t|&lt;br /&gt;    t.libs &lt;&lt; "test"&lt;br /&gt;    t.pattern = 'test/selenium/**/*_test.rb'&lt;br /&gt;    t.verbose = true&lt;br /&gt;  end&lt;br /&gt;  Rake::Task['test:selenium'].comment = &lt;br /&gt;    "Run the selenium tests in test/selenium"&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now you can simply call &lt;tt&gt;rake test:selenium&lt;/tt&gt; from a command line (with your test server and Jetty server running) and your tests will pop up in a new browser window and spit out the results at the end. If you do run any of the tests individually without using the rake task you will be faced with the problem of your test db not clearing out (for some unknown reason Rails does not seem to want to treat the Selenium tests as normal tests, and thus does not prepare the test database before running each test). We struggled with this for quite a while and had to finally dig into the rake tasks to find out how to tell MYSQL what we wanted it to do. The result was a small smorgasbord of ActiveRecord::Base commands to make a schema of the current test db, clear the db completely, and then rebuild the db using the just made schema. The following code was put into a test helper (which was required by the test file by using the &lt;tt&gt;test_helper :selenium&lt;/tt&gt; call) and called inside of the setup of the test:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def prepare_test_db    &lt;br /&gt;  abcs = ActiveRecord::Base.configurations&lt;br /&gt;  ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])&lt;br /&gt;  File.open("#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql", "w+"&lt;br /&gt;    ) { |f| f &lt;&lt; ActiveRecord::Base.connection.structure_dump }&lt;br /&gt;  ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])&lt;br /&gt;  ActiveRecord::Base.establish_connection(:test)&lt;br /&gt;  ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')&lt;br /&gt;  IO.readlines("#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql"&lt;br /&gt;    ).join.split("\n\n").each do |table|&lt;br /&gt;      ActiveRecord::Base.connection.execute(table)&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now you're test db will be cleared out no matter how you invoke the test. &lt;br /&gt;&lt;br /&gt;Now, go and use this information for the greater good. Share it and love it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4293464655956680856-8734927482935919585?l=siannopollo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://siannopollo.blogspot.com/feeds/8734927482935919585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4293464655956680856&amp;postID=8734927482935919585' title='169 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/8734927482935919585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4293464655956680856/posts/default/8734927482935919585'/><link rel='alternate' type='text/html' href='http://siannopollo.blogspot.com/2007/02/selenium-and-ruby-they-actually-work.html' title='Selenium and Ruby: They actually work together!'/><author><name>siannopollo</name><uri>http://www.blogger.com/profile/13970708413768615942</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>169</thr:total></entry></feed>
