General

Gems

Web Based

ARSettings

my first Ruby gem

ActiveRecord is great for abstracting your database, but not for dealing with 1-off values like settings. Where it might make sense to have a whole table full of users, it doesn't make so much sense to have a whole table for your contact information, which would only have one row. So, I wrote ARSettings, a gem to handle all of this without me having to think about it. It has its own table, and is responsible for serializing and deserializing the data without the user having to think about it any different from an in memory value.

It has generic settings (stored in the db under the name of the class you create, in this case in the 'settings' table).

ARSettings.create 'Settings'

Settings.has_setting :domain , :default => 'localhost:3000'
Settings.domain # => "localhost:3000"

Settings.domain = 'localhost:9292'
Settings.domain # => "localhost:9292"

You can namespace the settings.

EmailSettings = Settings.package :email
Settings.has_setting :enabled       # namespaced under settings
EmailSettings.has_setting :enabled  # namespaced under email
EmailSettings.enabled = nil
EmailSettings.enabled? # => false # has a boolean getter

Add to an ActiveRecord class.

class User < ActiveRecord::Base
  has_setting(:site_admin) { |user| user.name }
  has_setting :delete_account_after , 
              :instance => true , 
              :default  => 365 # days
end

Add to any class.

class Water
  ARSettings.on self
  has_setting :hydrogen , :default => 1
  has_setting :oxygen   , :default => 2
  has_setting :state    , :default => :liquid , :instance => true
end

Reflection

This was probably my first truly TDD project. I'd been wanting to work on one for a while, but was rather discouraged. I used Test::Unit, but added a few helpers to make the syntax a bit more RSpecish (in retrospect, I think that test/unit supports this syntax these days anyhow).

While I say it was TDD, it was not BDD, a distinction I did not understand at that time, but I think a guiding cuke would have been very beneficial, because there were many times where I just wasn't really sure what test I should write next. When I finished the functionality, and went to write a few examples of how to use it, I immediately realized I wasn't done! Had to go back and do a bit more work to make the interface usable. I think the full fledged BDD approach would have prevented this. But, I haven't really done a BDD project yet, so I'm speculating somewhat.

One thing I did that I'm happy with, but not sure if it's a good thing or not is to use shell scripts and rvm in my test cycle. This allowed me to test against Ruby 1.8.6 - 1.9.2, and ActiveRecord 2.3.3 - 3.0.1

Another thing that I was pleased with, I was trying to avoid big up front design, so I mostly just wrote tests and then coded. I found that the design emerged on its own, and I did find it to be rather elegant. The downside, though (and this is probably me implementing it incorrectly) was at one point I needed to do a large refactoring, a big piece of functionality moved from the settings class' methods into its own object, and the settings class instead delegated to that object. I found this to be incredibly daunting, it took about two days for me to move everything over, a huge number of tests needed to be changed, and a lot overhead was involved. This implies to me that I still have a poor understanding of the paradigm, and am simply not doing it right. This is one of the reasons I want to get in a place where everyone does BDD all the time for everything.

Code is on github.