ActiveRecord - Simple Key Value Store

Over the last few weeks I have been playing with the idea of having a simple database backed key value store using Rails ActiveRecord. The ActiveRecord class should act like a singleton where arbitrary keys can be set with a value of any type (simple values, hashes, arrays or complex objects). I have come up with the idea of using method missing to set and retrieve the key / value pair where the value's are saved as yaml and then cast back to the correct type when retrieved.

            class Application < ActiveRecord::Base
              set_table_name "application_settings"
              
              def self.method_missing(method, *args, &block)
                return self.send method, *args, &block if self.respond_to? method
                method_name = method.to_s
                if method_name =~ /=/
                  return self.set method_name.gsub("=", ""), args.first
                else
                  return self.get method_name
                end
              end
              
              private 
              def self.get setting
                entry = Application.where(:key => setting).first
                entry.nil? ? nil : YAML.load(entry.value)
              end
              
              def self.set key, value
                setting = Application.where(:key => key).first || Application.new(:key => key)
                setting.update_attribute(:value, value.to_yaml)
              end
            end
            

Below is the migration needed to setup the database table for your application settings class.

            class CreateApplicationSettings < ActiveRecord::Migration
              def up
                create_table :application_settings, :id => false do |t|
                  t.string :key
                  t.text :value
            
                  t.timestamps
                end
                add_index :application_settings, :key, :unique => true
              end
              
              def down
                drop_table :application_settings
              end
            end
            

Using the class it is possible to set a value to any arbitrary key by calling the setting name setter method just like it is a defined class attribute.

            Application.some_arbitrary_setting = 12903
            Application.my_hash_foo = { :foo => "bar" }
            

To retrieve the setting make a method call to the key name as if it were a defined class attribute.

            Application.some_arbitrary_setting
            => 12903 
            
            Application.my_hash_foo 
            => {:foo=>"bar"}
            
Tweet Me | Link To Facebook
Tom
Sunday, 4th December, 2011
gravatar
You lose dynamic finders (find_by_...) by overriding method missing and not calling super, though you could argue that in this case they are no longer required.
Other than that this is a neat solution.
Tom
Sunday, 4th December, 2011
gravatar
I think you shouldn't make get and set private, right now if the user wanted to set some keys that are determined programatically he'd have to resort to using send, that's a little ugly.
Sunday, 4th December, 2011
gravatar
I do think losing find_by_? in this case is fine. Also making get and set public would be a better idea for sure!