acts_as_setting – ruby dynamic setting class 2

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

  1. Fred Mon, 08 Nov 2010 18:57:29 UTC

    I’m searching for something like this: Fast, nested key-value pairs, using db-store, store arbitrary ruby objects (serialize via Marshal), preferably cached, native ruby api..

    Something akin to bdb or Tokyo Cabinet, but on ActiveRecord / Ruby steroids of course.

    Maybe associative array activerecord will show more hits. Maybe what I’m looking for is really Hibernate, or some kind of ORM, but I’m having a hard time finding it for sure.

    Use Case: For persistence of objects with minimal reads (cache) and writes (partly serializes)

    More searching..

    Of course ORM gives alot of results, now for some serious reading..

    Even more..

    Invented before: nosql, schemaless data and document dbs or whatever it was called. Neat concepts and I should be able to be find some wheel, like friendly or similar to that.

  2. Fred Mon, 08 Nov 2010 19:49:38 UTC

    After some more searching, unable to locate a general solution.

    Am thinking I could loop over the nested hash / arrays myself and attach / convert ActiveRecord objects to the elements or create an appropriate subclass. Then all I’d need to do is call save() if it has_changed() or preferably mass updating them using a temporary table.

    It’ll be general enough to act as a general solution for my project at least. Just surprised I cannot find this implemented already for such unstructured and non-formal data mapped onto RDBMS.

Comments