Archive for September, 2005

Design of a Rails application

Over the summer I quickly developed an application to take registrations online (clubrs.org in the sidebar). It worked and now we’re between registration periods and I have a chance to step back and do some work at a little more leisurely pace.

Now I’m looking to do two things:

  1. implement incomplete functionality
  2. refactor some of the design

I’d like to start with the design refactor so that the new areas are developed using the new design patterns. One goal is to make the application configurable as I’m considering commercial applications. Each club that uses it will likely have different requirements in regard to registration, team building and game scheduling.

One area which has nagged at me from the start is where to put the various bits of business logic.

Initially I put quite a bit in the controller. For example, in the payment controller, there’s a method to check if a registration should be complimentary (for some volunteers).

As I went along I started moving more logic like that into the models, which is better. But that still is less configurable than I’d like.

Now what I’m considering is this:

Controller: only application flow

Model: only persistence and associations

Modules: add modules for major areas of functionality – Payments, Registrations, Team Building, Game Scheduling.

The view/view helpers would be used as normal.

I think the main change will be to move most business logic out into modules. This will let me swap out modules to change the configuration.

For example, now we are considering a whole different way to put the teams together. Currently we have a group of volunteers who take all the registered players and put them onto teams. It turns out to be very hard and we get a lot of complaints from parents (if a kid isn’t on a team with a friend, doesn’t get the right coach, etc).

So we’re considering letting the parents place the child on a team at registration time. I’m thinking that if the team building functionality is encapsulated in a module I can swap which one is mixed in to the controllers and substantially change the application, even at run time.

This particular example of team building may be particularly difficult to solve as it will likely impact the flow of the application as well as the logic.

I’ll update this thread as I go along with any lessons learned. Please add any comments if you’ve come across similar design decisions and what you may have learned.

Static or Dynamic

I’ve read Dave Thomas’s view that many who are averse to a dynamic language are quite used to casting their objects in Java when they are retrieved from a collection. In doing some refactoring and cleanup today I came across this example:

invcAmnt = (BigDecimal)(BigDecimal)invoiceMap.get(agreementId);

When you really, really want to be sure. :)

Closures Blocks and Procs (oh my!)

This is a great explaination of Ruby’s closures. I’ve seen a number, but this one is very clear and concise. For one, I’d never really gotten that closures are just blocks. Also, you can see what Proc is all about. Definitely worth a read.

Martin Fowler on Closures

Incomplete Guide to FastCGI

The Incomplete guide to using FastCGI at DreamHost.

(Some or all of this may pertain equally to other shared hosting environments also.)

It’s Incomplete in that I want to get the few lessons learned out quickly rather than working out the guide in great detail.

Eliminate 500 Server Errors

I’ve gotten rid of my Rails 500 errors. I haven’t seen one in weeks.

1) Download fcgi_handler.rb available in the rails svn:

http://dev.rubyonrails.org/svn/rails/trunk/railties/lib/fcgi_handler.rb

This is post-rails 0.13.1 (as yet unreleased), and you’ll need 0.13 or newer to use it. Specifically, your dispatch.fcgi should include only these lines (uncommented at least):

require File.dirname(__FILE__) + "/../config/environment"
require 'fcgi_handler'
RailsFCGIHandler.process!

2) Copy fcgi_handler.rb to your lib directory.

3) There is no step three!

You may see quite a few dispatch.fcgi processes, but they will exit gracefully instead of causing the 500 errors.

Restart your FastCGI Processes

There is the nice way and the effective way:

killall -USR1 dispatch.fcgi
killall -9 dispatch.fcgi

The first method will tell all processes to exit the next time they are called. I’ve found that they tend not to get cleaned up. (More on that later.) If you do this, even if you get a lot of processes running, you’ll find your app is happy and stable. DreamHost has a process sweeper that should clean up if you get too many processes.

The second will nuke them all even if a process is in mid-request. Mua ha ha. Before switching to the new fcgi_handler I did this each morning. Now I haven’t done it in a couple of weeks.

Eliminate Bugs in your App

This is really important. Even a ‘bug’ like not having a robots.txt file at your root can cause server errors, which can damage dispatch.fcgi processes, which then cause 500 errors (if you don’t use the fcgi_handler above).

Search your production.log and eliminate any issues, big or small.

Setting up a Debian development server

Some time ago I decided I’d really like to have an environment at home that mirrors a DreamHost server to enable me to do more testing and get a look under the covers at the various config options.

I also wanted to have a Trac install for clubrs.org.

I had a PIII with a 20GB drive and 512MB ram that I’d just retired from family use and it seemed a perfect candidate.

I really wanted 2 features in this server: security and ease of administration. The only machine I’ve had hacked was a Red Hat server and it was because I didn’t keep up with security releases. I want that to be as automatic as possible – I’m a developer, not a system admin. :)

I thought about going with FreeBSD since that seems to be popular with Rails developers and also is known as a secure OS. I also thought about Ubuntu for ease of use, but since DreamHost uses Debian I went that direction. So far at least, I’m very glad I did.

I’ll post a few articles covering the process: the trade-offs in OSes, the download/install process and setting up Trac.

The conclusion is that I’m very happy with Debian. In large part because it is a popular enough distribution that there are how-tos for everything and they seem to be very up to date. It installed easily and managing and updating packages is easy.

More to come….