acts_as_setting – ruby dynamic setting class

Posted by chad on June 30, 2008

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 } }
Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

Comments