Tech Per

13 Feb

ActiveRecord Associative Array Directly Into The Database

The other day, I came across the following code in a Rails project of mine:

value = SystemSetting[:some_key_here].to_i

Hmm, I could not recoqnize SystemSetting, so I guessed it was something a colleague of mine had introduced while I was away from the project. I guessed it to be an associative array, setup in the rails environment files, to hold various application system settings. I guessed wrong! SystemSetting turned out to be a real ActiveRecord model class, which simply acted as an associative array directly into a table in the database. And thanks to ActiveRecord and the Ruby language, it could do this in a very elegant way, in only a few lines of code.

Here is the system_settings table:

Column Name | Data Type
-----------------------
id          | INTEGER
name        | VARCHAR
value       | VARCHAR
-----------------------

And here is the clever ActiveRecord model class:

class SystemSetting < ActiveRecord::Base
  def self.[](name)
    find_by_name(name)
  end

  def self.[]=(name,value)
    setting = find_by_name(name)
    if setting
      setting.value = value
      setting.save
    else
      setting = self.create(:name => name, :value => value)
    end
  end

  def to_i
    value.to_i
  end

  def to_s
    value
  end
end

So what are these few ruby lines doing? For starters, it is overriding the array access methods [] and []=, in the two first methods. In the first method, the array entry read, it implements it as a find_by_name ActiveRecord call, that simply returns a SystemSetting instance, if the name matches the array index name. In the second method, the array entry assignment, it implements it as either an update of an existing row on the array index name, or as a create of a new entry, if the name is not found. Lastly, there are the to_i and to_s methods, which provides easy typed access to the value of an entry.

In my eyes, this is a damned elegant trick!

The class does not provide help for cleanup in the array. I think this could easily be done, by deleting entries by name, if nil are assigned to them.

3 Responses to “ActiveRecord Associative Array Directly Into The Database”

  1. 1
    Mr eel Says:

    That is indeed, very simple and elegant.

    Perhaps the only improvement I could suggest is caching the records as they are returned. If you happen to access a particular setting repeatedly, you’ll end up with multiple database hits.

  2. 2
    robert shell Says:

    If for like this, you may like the plugin I wrote for my setting. (see http://biorails.org/svn/biorails/plugins/alces_act_as_setting/ ) Its also add the ability to use the setting name as a class level method as well as a array eg.

    SystemSetting['xxx']
    SystemSetting.xxx
    SystemSetting.xxx = ’ss’

    To use is a simple acts_as_setting directive with a link to a xml file to define names and load initial values from xml.

    class SystemSetting “#{RAILS_ROOT}/config/system_settings.yml”
    end

  3. 3
    chad Says:

    I wrote a slightly different version that uses activerecord and the database (no need for xml here), but that creates members on the class to make the calls much faster and save the database hits.

Leave a Reply

© 2009 Tech Per | Entries (RSS) and Comments (RSS)

GPS Reviews and news from GPS Gazettewordpress logo