Environment specific configuration files can be a pain in version control. Especially when multiple developers keeps clobbering each other on updates.

At Elevator Up we use Subversion almost exclusively. One useful approach is to first svn:ignore each config file. With Rails applications I usually ignore:

  • database.yml – Database connection for Rails
  • deploy.rb – Capistrano Deployment Recipe
  • httpd.conf – Apache VHost configuration
  • mongrel_cluster.yml – Mongrel Cluster Config
  • Any .so, .dll, or .bundle sitting in RAILS_ROOT/lib

Then I save specific names for the environments they are used in. Most times with Elevator Up applications we have at least 3 environments:

  • My Development Box
  • Pre-Production Machine
  • Production Machine

I append the environment as an extension to the file, and throw those into version control.

  • database.yml.zach
  • database.yml.preprod
  • database.yml.prod

Then I either create a symbolic link to the file I want to use (or if in Windows environment, copy the file).

It may seem silly at first to have different copies of the file in version control, however I’ve found at least these benefits:

  • Database Config – Username / Password / Database Names / Database Engines change per machine
  • Deploy Scripts – Allow you to choose what is getting deployed cap -f config/deploy.rb.prepod deploy
  • Apache Config – IP Addresses in VHost are almost always different
  • Mongrel Cluster – Along with IP Addresses, Mongrel Ports may also be different

Paranoid Testing

May 22nd, 2007

I had the opportunity to attend the XP West Michigan meeting tonight, and listen to the energetic speaker Elisabeth Hendrickson from Quality Tree Software.

It was a great talk about the common mistakes in Agile Development. Hopefully her presentation will be available online soon. It’s easy for agile developers to get puffed up and pat ourselves on the back because we write automated tests. Elisabeth highlighted important issues that agile development doesn’t solve.

I especially liked her point about developers being on two sides of a scale. Either their too confident: in code, in deployment or in users interactions. Or they’re too paranoid, writing tests to cover all possible scenarios. Striking a balance is difficult.

I definitely have followed the path of the paranoid developer, trying to test as much as possible. Even in writing Eventable I have had to scale back the testing intensity. My problem always seems to be the test code becomes a weight dragging down the agility of the code. In essence more time is spent maintaining test code than the actual production code.

I’ve tried following a few principles when writing tests.

Test names should be close to readable sentences.

RSpec and BDD hit this right on the mark. Don’t be scared of especially long method names. test_users_should_have_multiple_emails is extremely descriptive. And if you lose track of what you’re really testing, the name will put you back on track. When trying to fix failing tests, expressive test names give me a good picture as to what functionality is broken.

Keep the tests short.

Tests should be the documentation for the code, and large tests are difficult to grok. I try to keep my tests under or around 5 lines. When it starts pushing 10 – 15 something needs to be abstracted, even if it’s moving most related assertions into a method call used only by that one test.

Fire Copy and Paste

Copy and Paste are scam artists. They have no business in software development. If there was ever a gluttonous act for coders, it’s to duplicate code and change only bare essentials. Be it production or test code (the latter being just as important) if you find yourself copying and pasting to add in a quick test, a flag should be raised.



Update 5/24/07

Here are the slides for her presentation.

Older Rails and Mongrel

May 21st, 2007

One of the useful features of Rails servers (Webrick, Lighttpd, and Mongrel) is to see the development log going to standard out. However when using Rails before version 1.2 and Mongrel, you don’t get that nicety.

I had to dip into a few applications using pre Rails 1.2, and having a separate terminal open for the log became annoying. This minor change keeps you from tailing in another terminal.

In RAILS_ROOT/config/environments create a new environment called mongrel.rb. Copy the contents of development.rb into it and throw this line at the bottom.

config.logger = Logger.new(STDOUT)

Then start Rails with mongrel_rails start -e mongrel

ack

May 20th, 2007

At Elevator Up I spend roughly 90% of my time buried in TextMate coding in Ruby. Initially I used grep when searching for text out of command line habit. I also toyed with TextMate’s built in searching, but that took too long, especially when I froze Rails.

Then I came across ack. All I can say is wow. I’m not a big fan of perl, but this little script does a great job. It even ignores those pesky .svn directories.

Give it a shot, I use the standalone version which is just a big perl script to toss in your PATH.

Working at Panera

May 17th, 2007

At Elevator Up, Aaron and I frequently work at Cafes like JPs Coffee. But Panera Bread is quickly becoming my favorite place to work.

They have such a laid back atmosphere with excellent service, great food at a low price. And as if that wasn’t all, every one I’ve been at has provided free WiFi. They even have signs advertising Power Outlets in the building.

Truly a perfect place for a developer to focus for a few hours.

Picnik

May 15th, 2007

Recently I got Brit hooked on Flickr and it only took her 3 days to hit her monthly bandwidth quota. However, what’s more interesting is that I needed to find a very intuitive application for her to edit photos quickly. And those of you who know me, I’m all big into thin clients, so I started googling.

I came across one called Picnik and holy cow is it awesomely simple / powerful. I’ve caught myself using it to resize and crop photos rather than pulling them into The Gimp. And it integrates easily into Flickr or Picasa.

A very neat find, especially for minor picture changes.

When reading the Rails documentation for validates_presence_of I eyed the warning pertaining to foreign keys.

Rails Documentation for 1.2.3

I came across this article and when running the examples written, I found the same errors.

Stumped, I started crawling through the Rails code. I documented the behavior with this small rails app which includes the Rails 1.2.3 frozen in1.

Instead of using invoice and line_items, I decided to simply use parent and child


  Parent:
    class Parent < ActiveRecord::Base
      has_many :children
    end

  Child:
    class Child < ActiveRecord::Base
      belongs_to :parent
      validates_presence_of :parent, :name
    end

  Invalid Code:
    >> p = Parent.new(:name => "Dad")
    => #<Parent:0x23ac8f4 @attributes={"name"=>"Dad"}, @new_record=true>
    >> c = p.children.build(:name => "Son")
    => #<Child:0x2367858 @attributes={"name"=>"Son", "parent_id"=>nil}, @new_record=true>
    >> p.save!
    ActiveRecord::RecordInvalid: Validation failed: Children is invalid
            from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/validations.rb:764:in `save_without_transactions!'
            from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/transactions.rb:133:in `save!'
            from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:59:in `transaction'
            from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/transactions.rb:95:in `transaction'
            from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/transactions.rb:121:in `transaction'
            from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/transactions.rb:133:in `save!'
            from (irb):3

  Valid Code:
    >> p = Parent.new(:name => "Dad")
    => #<Parent:0x22b9f28 @attributes={"name"=>"Dad"}, @new_record=true>
    >> c = p.children.build(:name => "Son", :parent => p)
    => #<Child:0x229626c @attributes={"name"=>"Son", "parent_id"=>nil}, @parent=#<Parent:0x22b9f28 @attributes={"name"=>"Dad"}, @new_record=true, @children=[#<Child:0x229626c ...>]>, @new_record=true>
    >> p.save!
    => true

What seems to be happening is the validations are called twice. The first time with the parent_id of nil, and then the second with the parent_id (obviously now it’s saved the Parent and is going to actually save the Child).

Perhaps later I will crawl through the Rails code and submit a patch to automate the setting of association variable, but I’m still debating if that’s the correct thing to do.

What gets really odd is if I take out the validate_presence_of from the Child and use the first method, both Parent and Child get saved, and the Child has the foreign key set.


  Parent:
    class Parent < ActiveRecord::Base
      has_many :children
    end

  Child:
    class Child < ActiveRecord::Base
      belongs_to :parent
      validates_presence_of :name
    end

  Valid Code:
    >> p = Parent.new(:name => "Dad")
    => #<Parent:0x23ac8f4 @attributes={"name"=>"Dad"}, @new_record=true>
    >> c = p.children.build(:name => "Son")
    => #<Child:0x2368dfc @attributes={"name"=>"Son", "parent_id"=>nil}, @new_record=true>
    >> p.save!
    => true
    >> p.children
    => [#<Child:0x2368dfc @attributes={"name"=>"Son", "id"=>2, "parent_id"=>2}, @new_record=false, @errors=#<ActiveRecord::Errors:0x233fe84 @errors={}, @base=#<Child:0x2368dfc ...>>>]

1 To run the example:

  tar xvfz foreign_key_validations.tgz
  cd foreign_key_validations
  rake db:migrate
  rake test

Buck

May 12th, 2007

So we bought a 2nd Great Dane, as if Brutus wasn’t enough of a handful.

Meet Buck: Buck

We called the Breeder for Brutus’s papers, and while she was on the phone we asked about one of his brothers who had injured his leg when he was a few weeks old. She said that someone had brought him home, but then decided to return him.

So going against my better judgment we decided to give this poor pup a good home. Boy these two are going to be huge.

Ready for Nap Time

Brutus

April 30th, 2007

Yesterday we brought home our newest addition to the Moazeni household. Meet our new Great Dane. Brutus:

Brutus

He’s been quite the handful, and boy is he scrappy. He does not have any qualms about showing off his puppy bark. His first encounter with Mocha he gave her a few tiny growls and barks and now she steers clear of him.

Brutus's first meeting with Mocha

So if see this little Harlequin on the street, watch out. He’ll give you a piece of his mind. Just ask his chew toys and my socks.