Drinking the Rails Kool-Aide, Revisited

A few years ago, I jotted down some thoughts about working with Rails in an Agile environment, under the somewhat provocative title I’ve used for this post. Here are some of those ideas. I’ve expanded on some, commented and clarified others. By no means an exhaustive list, here are some of the paradigms I’ve used when developing with Rails:

  1. Embrace change. Forget how you did it before. Reproduce the results, not the methodology.
  2. Embrace design. Accept that the two primary work areas for a development project are architecture and data modeling. 80% of your project effort should be in these areas. Not coding.
  3. Design from square one. Don’t start by coding. Start with architecture. Model your database on a whiteboard. When you have the architecture where you think it should be, write tests. Coding too much too early will hamper success. If you can’t explain where you’re going, how can you know when you’ve arrived?
  4. Databases are for data. If you have data to store, put it in the database. If you need data, get it out of the database. Flat files in the file system are almost never what you want in a web application.
  5. Understand the framework’s inherent biases. For example, Rails doesn’t play well with certain concepts that are de rigueur in the database world, like domain keys, composite keys (although there’s a plugin for that), etc. There’s a longer post in this one, I think.
  6. Embrace DRY. When you do code, embrace “don’t repeat yourself” and be draconian about it. Don’t program via cut-and-paste.
  7. Leverage the community, or, to put it another way, Don’t Repeat Others Either. The initial thought when sitting down to code should be “where do I look for something already written that does what I want?” rather than “how am I going to do this?”
  8. Test everything. Don’t ship code for which you haven’t written formal tests.
  9. Don’t optimize the framework away. Optimization efforts should start with “How do I leverage the framework, given the overhead that I’ve paid already?” Worry about reducing the overhead only after you’ve gotten everything you can out of the framework.

Capistrano deployment woes

Deploying via Capistrano is supposed to be painless. Unfortunately, the Dreamhost Wiki entry on it gives an approach that doesn’t work for me.

Specifically, I either timeout or get a connection refused on the connect.

I have public key authentication working. I can ssh to the account from the shell prompt and not be asked for a password.

I also know that it’s not a problem with Net::SSH, because hand-tooling the connection from irb works:

require 'net/ssh'
Net::SSH.start('www.drinkingfromthefirehydrant.com','hydrant',:keys => %w(/Users/jnich/.ssh/id_dsa)) do |ssh|
    output = ssh.exec!("hostname")
    puts output
end

My config file looks like this:

set :user, 'hydrant'
role :app, "www.drinkingfromthefirehydrant.com"
ssh_options[:keys] = %w(/Users/jnich/.ssh/id_dsa)

Given this, I should be able to run “cap shell” and enter a command like “on app hostname” and see it work, but instead I get things like

connection failed for: app (Errno::ECONNREFUSED: Connection refused – connect(2))

Aside: In looking into how Capistrano uses Net::SSH, I found this page from Jamis that describes how Capistrano uses Net::SSH internally. Of note is this particular line:

config.logger = Capistrano::Logger.new(:output => "/dev/null")

One of the reasons people sneer at Rails as a platform for enterprise-class applications is crap like this. If you hard-coded the logger to /dev/null in a production class, don’t expect people to take your code seriously, no matter how many f-bombs your team lead drops when making public speeches.

Updated:I’ve resolved my Dreamhost/Rails deployment issues without using Capistrano for the moment. Somehow, in the course of messing around, I managed to make my Dreamhost home directory group-writeable, which had the effect making the Dreamhost sshd ignore my .ssh directory (since it was potentially compromised.)

To deploy, I simply did an svn checkout. That makes more sense to me than the Capistrano method, which involves endless messing around with symlinks and archived copies of the application.