11.15.2007

Storing System Preferences in the Database

Here is a simple way to store system preferences in the database for a Ruby on Rails application. This simple solution offers no caching, so accessing the same preference many times will result in many database request. Suggestions for per request caching are welcomed.

Using the code bellow, one can access preferences like this :
admin_email= Preference["admin_email"]
First, let's start with a migration that will create a table in which we can store many types of preferences :
class CreatePreferences < ActiveRecord::Migration
def self.up
create_table :preferences do |t|
t.column :setting, :string
t.column :type, :string
t.column :value, :string
end
end

def self.down
drop_table :preferences
end
end
Now, we create the model. Because we want to be able to get many types of preferences (and eventually validate their value in different ways), we create a base Preference class and many subclasses for all the types of preferences we want to have. Some subclass will override the value and value= methods to convert the value to the proper type :
class Preference < ActiveRecord::Base
validates_presence_of :setting

def self.[](setting)
setting= self.find_by_setting(setting)
setting.nil? ? nil : setting.value
end
end

class UrlPreference < Preference
end

class EmailPreference < Preference
end

class StringPreference < Preference
end

class IntegerPreference < Preference
def value()
self[:value].nil? ? nil : self[:value].to_i
end

def value=(v)
self[:value]= v.nil? ? nil : v.to_s
end
end
Note that we could add validation for the value attribute in UrlPreference and EmailPreference to validate the format of the value.

1 comment:

Pauliephonic said...

How about adding caching so you only hit the db once if the params don't change


class Preference < ActiveRecord::Base
validates_presence_of :setting
@@cached_data = {}
def self.[](setting)
if @@cached_data[setting]
res = @@cached_data[setting]
else
res = self.retrieve(setting)
@@cached_data[setting] = res if res
end
res
end

def self.retrieve(setting)
setting= self.find_by_setting(setting)
setting.nil? ? nil : setting.value
end
end

AdSense Links