Autotest with custom growl notifications in Leopard 5

Posted by unixmonkey on January 17, 2008

Autotest is part of the ZenTest suite for testing ruby and rails apps. Instead of running ‘rake test’ every time you want to run your tests, simply open another tab in your terminal, browse to your rails project directory and run ‘autotest’. It will run your test suite and sit there waiting for any file to be modified. When you edit any file in your rails project, autotest will automatically run your tests again.

To install ZenTest and autotest, open a terminal and run ‘sudo gem install ZenTest’.

This is great, awesome even. I don’t want to understate how useful this is, its like breathing when doing test-driven development, but when I’m coding, I’ll often have a different terminal up front with a script/console shell or tail-ing the development log. I want my tests to get in my face when something goes wrong.

The way to do this is with Growl on OSX, Snarl for Windows, or several other similar pop-up notification apps.

As of this writing, the latest version of Growl is 1.1.2, the ZenTest Gem is 3.8.0, and OSX Leopard is 10.5.1. I installed Leopard as a clean install.

After downloading and installing Growl, while the .dmg is still mounted, open a terminal and run ‘/Volumes/Growl 1.1.2/Extras/growlnotify/install.sh’.

This will put a commandline tool called ‘growlnotify’ in your /usr/local/bin dir that is used to pop up those messages. Now you can use a text editor to create a ~/.autotest file.

Lets start simple and check that growl is working with autotest, add this line to your .autotest file:

require ‘autotest/growl’

Then save, and go into your Rails project and run ‘autotest’

If all the pieces were installed right, you should get some nice popups when you run autotest and each time you modify a file in your rails project directory.

Lets pretty this up a bit by over-riding the Autotest::Growl module in our .autotest file. I’ve pretty much copied this verbatim from /Library/Ruby/Gems/1.8/gems/ZenTest-3.8.0/lib/autotest/growl.rb
only I’ve added an image directive to the autotest hooks, a nice red rails logo for test failures, and a green one for test passes, then changed the growl method to substitute my images into the growlnotify command. Be sure the modify the image paths for your images directory.

# ~.autotest
 
require 'autotest/redgreen'
require 'autotest/growl'
 
module Autotest::Growl
 
  def self.growl title, msg, img="/Applications/Mail.app/Contents/Resources/Caution.tiff", pri=0
    title += " in #{Dir.pwd}"
    msg += " at #{Time.now.strftime("%I:%M %p")}"
    system "growlnotify -n autotest --image #{img} -p #{pri} -m #{msg.inspect} #{title}"
  end
 
  Autotest.add_hook :run do  |at|
     growl "autotest running", "Started"
   end
 
   Autotest.add_hook :red do |at|
     img = "/Users/djones/.autotest_images/rails_fail.png"
     growl "Tests Failed", "#{at.files_to_test.size} tests failed", img, 2
   end
 
   Autotest.add_hook :green do |at|
     img = "/Users/djones/.autotest_images/rails_ok.png"
     growl "Tests Passed", "Tests passed", img, -2 if at.tainted
   end
 
   Autotest.add_hook :all_good do |at|
     img = "/Users/djones/.autotest_images/rails_fail.png"
     growl "Tests Passed", "All tests passed", img, -2 if at.tainted
   end
 
end

Now create a .autotest_images folder in your home directory and put these images in there (I got them from here), or you can use your own.

rails_ok.pngrails_fail.png

Thin: slimmer and faster than mongrel

Posted by unixmonkey on January 05, 2008

We all know mongrel is the bees knees when it comes to serving Rails or Merb apps, even if its creator had a meltdown.

But there is a new kid on the block named thin that claims to run Rails apps almost twice as fast as mongrel. Check the graph.

Thin vs mongrel vs webrick comparison chart

A simple ‘gem install thin’ and going into your rails app and issuing ‘thin start’ is enough to get you shedding weight.

This is definitely something I’ll be playing with for the next few days.

Setting up a production rails server step-by-step

Posted by unixmonkey on December 27, 2007

Pushing your app to the real world with Rails can be a very daunting task to someone who is used to just uploading flat html or php files.

If you’ve never dealt with Apache, mod_rewrite, or proxy servers, prepare to spend a lot of time hammering out a solution. Worried about performance, or your need to scale out at a later date? Pick a solution that won’t leave you wondering if your site will be able to take a spike in traffic.

For Rails, there are lots of deployment strategies, some are tuned for compatibility with shared hosting (fastcgi), and some are built for speed and minimum configuration (Litespeed Nginx and Lighttpd), and some are built to leverage the strength and flexibility of stable and established server software (Apache+Mongrel).

If you want to scale, you’re going to need a load balancing proxy. The choices here are pound, pen, and apache’s mod_proxy_balancer.

An abundance of choice is a double-edged sword. Competition is good in any arena, but it makes it very hard for someone who hasn’t tried them all to choose one.

I’ve chosen to setup my Rails server using the Apache+Mongrel+mod_proxy_balancer combination.

For the operating system, I’ve chosen the newest Ubuntu 7.10 (Gusty) server. Ubuntu uses the Debian-style apt package management, but with more current packages than Debian stable, and is the current cool kid on the block for Linux systems. I have been using Ubuntu for years and can attest to its stability and cutting edge (but not bleeding edge) packages.

I’ve gone through and built a Rails server by hand before, but poorly documenting what I had done, and not securing it properly. When I stumbled upon Slicehost’s server setup articles, I knew I had found exactly what I needed to build a server configured like a pro, and all the documentation I should have written in the first place.

Here is the step-by-step setup for a production Rails server. I’ve tested this setup and can vouch for its awesomeness. I encourage you to make some changes specific to your setup where appropriate. You should be able to skip unneccesary stuff like php and virtual hosts if you don’t need them.

Ubunty Setup – part 1
Ubunty Setup – part 2
Myql and Rails
Apache and PHP
Apache Virtual Hosts
Vhosts and permissions
Apache Vhosts, Rails and Mongrels
Mongrel Clustering
Subversion intro
Setting up svnserve
Securing svnserve with ssh
Setting up Capistrano
Setting up Piston to manage plugins

As you can see, most of these are from Slicehost’s documentation articles. They also detail setup for several other major linux distributions and other deployment strategies like nginx. Major props to slicehost for putting such excellent documentation together.

Twas the night before Christmas

Posted by unixmonkey on December 24, 2007

Twas the morning before Christmas, and all through the office, not a creature was stirring, but me and my mouse. The code was checked in to the repo with care, in hopes a new feature soon would be there.

I sit in my sweater and hear the keys tap. I’m thinking of taking a stare-at-the-screen nap. When out in the server room there arose such a clatter. I jumped from my desk to see what was the matter. Away to the NOC I flew like a flash. Tore open the door and stroked my mustache.

The LEDs in the rack set the room all aglow, and gave a luster of blue and red, don’t you know? When what to my bloodshot eyes should appear, but a shower of sparks shooting out from the rear.

Out popped a fat man who ran out plenty quick, I knew in a moment it must be saint Nick. You bastard! I cried, and I called for my crew. Now, Mike!, Now Matt!, Now Jeremy!, Matt and Chicago Matt too! To the top of the building! Climb up that side wall! And get that fat jerk before his deer dash away all!

When we got to the top we had missed him by seconds, and the feeling in my gut was very much unpleasant. Back down in the server room the hard drives had been pulled, the tapes were all strewn out, and it was starting to flood.

That bastard had blown some metal filings in the air intake, then the power went out and it was all I could take. I went down to the bar and ordered a brew, then ordered 10 whiskeys and downed them all too.

When I came back to the office and threw up on the floor. The boss handed my my last paycheck and kicked me out the door. I got a new offer the very next day, making much more than double the pay. Thank you Santa, for this Christmas-time gift. Next year I’m definitely leaving you a tip.

Updating Broken Rubygems to 1.0.1 on Ubuntu 7.10 Gusty 1

Posted by unixmonkey on December 21, 2007

If you tried to update rubygems today like me, its possible you got hit with a nasty error message running gem after the successful update to rubygems-1.0.1.

root@localhost ~:#gem -v
/usr/bin/gem:23: uninitialized constant Gem::GemRunner (NameError)

gem_runner needs loading, so lets fix that by adding a require at the top of/usr/local/lib/site-ruby/1.8/rubygems.rb

...
require 'rubygems/rubygems_version'
require 'rubygems/defaults'
require 'rubygems/gem_runner' ## add this line
require 'thread'
...

There we go, now lets try:

root@localhost ~:# gem -v
1.0.1

Hooray! Working rubygems!

Update:

I found this is due to a problem with just the apt packages, and re-downloading and installing the tar.gz from rubyforge will also solve the problem.

Rails exceptions and debug trace even in production mode? 11

Posted by unixmonkey on December 17, 2007

During my recent adventure of setting up a production server for my rails applications, I stumbled upon some strange behavior where if I typed in a non-existent route or caused rails to barf all over itself, it would still show me a debug stack trace instead of the 400.html or 500.html living in /public

I uncommented the ENV[‘RAILS_ENV’] ||= ‘production’ line in /config/environment.rb, and the behavior persisted. I created a controller and view to echo out the environment, and did confirm that the app is running in production mode.

Googling only led to minor success where it was alluded in 1 or 2 posts that rails might think it is still running locally.

I started to eye my Apache mod_proxy_balancer + mongrel_cluster arrangement, where the cluster is set to spawn instances on 127.0.0.1 (localhost). After changing that local address to the outside facing address (192.168.x.x) and accessing it at that address in my vhost conf. Things were working as expected.

Now why would rails act this way? Searching the Rails API led me to the rescue_action and rescue_action_in_public methods, which led me to the local_request? method of determining which of the previous methods get called.

Great, now I’ve found the culprit. The code looks like the below:

# from rescue_action
if consider_all_requests_local || local_request?
  rescue_action_locally(exception)
 else
  rescue_action_in_public(exception)
end
 
#local_request?
def local_request?
  request.remote_addr == LOCALHOST and request.remote_ip == LOCALHOST
end

An easy fix is to drop a method that overrides this in application.rb

def local_request?
  return false if RAILS_ENV == 'production'
end

So, if you are having trouble making your app behave like its in production mode, give it a little spanking and remind it not to trust strangers with its debug trace.

Rapid Rails Deployment with Heroku Beta

Posted by unixmonkey on November 21, 2007

Today I got an email from heroku.com to beta test their rails hosting. Its pretty cool as it provides a web interface to setting up and editing your ruby on rails applications.

Within seconds of my getting the email, I had logged in and created a new rails app. Heroku automatically added a database.yml file pre-populated with the correct database connection info.

I wanted to see if I could get mephisto running quickly, as my host for unixmonkey.net had gone down last week and shows no sign of returning. I opened their interactive rake terminal and ran db:schema:load and db:bootstrap and my app was instantly available to me to log in and start configuring.

Everything was working fine for several hours while I was setting up to make my first huge post, but them I went to check it out at 6pm, it was down with a 500 error (ngnix), even the main heroku.com was down with a “zero sized reply”. But I checked again 2 hours or so later, and it was back up.

This is hands-down the easiest deployment I’ve ever seen. Either start with a fresh rails app, or import yours as a gzipped tar file. The only downsides so far:

* There is is a 10mb limit per app, so you can’t freeze rails in your vendor directory.
* There is a bandwidth limit I hit almost immediately after making my app public, and you can’t admin your site at all when overlimit, best you can do is export a dump of your app.
* Your app is always running in development mode. (production and other are planned for later release).

All these are likely just part of growing pains, and will be addressed eventually.

I sent an email to their support staff and my questions were addressed within hours, even late on a Saturday. You can tell its a labor of love.

Sign up for the beta. Its really cool.

Big Nerd Ranch Ruby on Rails Retreat

Posted by unixmonkey on November 19, 2007

After poking around with Ruby on Rails and reading every book and following every tutorial I could get my hands on for over 5 months, I decided to get real and sign up for the Big Nerd Ranch Ruby on Rails course being taught by Charles Brian Quinn, consultant for Highgroove Studios and co-founder of Slingshot Hosting.

I hadn’t previously heard of Big Nerd Ranch, so I was a little worried about the quality of the course, but with the Pragmatic Programmers Rails course being only two days, I felt I needed more time to be completely absorbed in the course material. The Big Nerd Ranch approach to removing you from from all distractions in a quiet, comfortable setting with a very small class size seemed to be just what I needed to focus and regroup.

Continue reading…

Skinning your entire Rails app

Posted by unixmonkey on September 18, 2007

Say I want to deploy my app as a service to several good customers, but I want my app to share the exact layout as each customer site, so it appears to be an internal app to their company and its own clients. I take thier CSS and HTML markup, and make it into a template to wrap around my app’s content.

When I took to task to replicate that functionality in Ruby on Rails, I wasn’t certain would be easily accomplished. All the tutorials I’ve read list template switching as purely CSS affairs. Using CSS to change the presentation of your site is a fine thing, but isn’t enough if you are looking to completely copy the look and feel of a client’s website with your app dropped in.

It took some thought and a little help from the community.

Previously, the system I was used to accepted a site variable passed with the login form that told which template to render. like http://myapp.com/?site=ibm

That’s ugly and really obvious to what it is doing, but what other way is there to know which template to render?

I recall setting up accounts at a handful of sites that were in the format of: http://myusername.myapp.com

This is known as using a subdomain as an account key. Luckily, there is a very simple plugin to set that up in Rails http://wiki.rubyonrails.org/rails/pages/HowToUseSubdomainsAsAccountKeys

After setting up the plugin, I’m able to access the subdomain name anywhere in the app. Good thing, because I need to access it in application.rhtml (or .haml)

 
<% # if there's a subdomain, render the partial of the same name -%>
<% if account_subdomain -%>
    <% # first check to make sure account_subdomain is valid and in accounts table  -%>
    <% @account = Account.find_by_username(account_subdomain) -%>
    <% unless @account.nil? -%>
        <%= render :partial => "layouts/"+account_subdomain %>
    <% else -%>
        <% # There's a subdomain, but it isn't valid. Render default template -%>
        <%= render :partial => "layouts/default" %>
    <% end -%>
<% else -%>
    <%= render :partial => "layouts/default" %>
<% end -%>

Notice in the above, that there are no :yield statements. That’s because :yield can live in a partial too. I’ve set up a partial for each subdomain listed in my database in app/views/layouts, and added some logic to render the default layout when a subdomain either isn’t present or is invalid.