In any large software project there is a concept of setting or configuration. In .NET, there is the System.Configuration class. Rails doesn’t have anything like this, but Most of the time, I have some need to roll my own class for this I recently have been using a setting class I created that loads settings from the database and stores them as constants on a class called ‘Setting’.
My goals were:
1. No repeated hits to the database just to access a property, except occasional reloads for an update to a setting in the database.
2. Runtime errors if a setting doesn’t exist. No returning ‘nil’ if a setting is mistyped.
3. Ability to update settings across multiple machines, in a reasonable amount of time. In this case, five minutes is reasonable.
This code is in lib/setting.rb (i’m still not sure why but i couldn’t get this to work when inside the main setting.rb file in the model directory):
class Setting
def self.load_settings
Setting.find(:all).each do |s|
logger.debug "Loaded Setting: #{s.name}: #{s.value}"
Setting.instance_eval do
isnum = ((s.value.to_i.to_s == s.value.to_s) rescue false)
eval "def #{s.name}\\n#{s.value}\\nend" if isnum
eval "def #{s.name}\\n\"#{s.value}\"\\nend" unless isnum
end
end
end
self.load_settings
end
Here’s the super simple migration in the pre-rails-2.0 migration format:
class CreateSettings < ActiveRecord::Migration
def self.up
create_table "settings", :force => true do |t|
t.column "name", :string, :limit => 50, :default => "", :null => false
t.column "value", :string, :default => "", :null => false
end
add_index "settings", ["name"], :name => "settings_name_index"
end
def self.down
drop_table :settings
end
end
Here’s the ‘main’ setting class:
class Setting < ActiveRecord::Base serialize :value end
In environment.rb, in order to reload the settings every five minutes:
require 'thread'
Thread.new { loop {sleep(300); Setting.load_settings rescue nil } }