public
Last active — forked from jimeh/README.md

A simple key/value store model for Rails using the database and memcache

  • Download Gist
README.md
Markdown

Rails Setting model

This is a semi-quick key/value store I put together for a quick way to store temporary data related to what's in my database, in a reliable way. For example, I'm using it to keep track of where a hourly and a daily crontask that processes statistics left off, so it can resume only processing and summarizing new data on the next run.

Code quality most likely is not great, but it works. And I will update this gist as I update my project.

How It Works

The settings table has two columns, a key and a value column. The value column is serialized, so you can technically store almost anything in there. Memcache is also used as a caching layer to minimize database calls.

Example usage

# fetching a value
>> Setting.hello
=> nil

# setting a value, writes it to memcache, and saves or updates a database
# record is the form of {:key => "hello", :value => serialize(["world"])}
>> Setting.hello = ["world"]
=> ["hello"]

# fetching the value again, which will only read from memcache
>> Setting.hello
=> ["hello"]

# force fetch from database and update memcache
>> Setting.hello!
=> ["hello"]

# remove the hello key from memcache and the database
>> Setting.hello = nil
=> nil

# default memcache expire_in option is 6.hours, you can change it...
>> Setting.__cache_expires_in = 1.hour
=> 3600 seconds
create_settings.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class CreateSettings < ActiveRecord::Migration
def self.up
create_table :settings, :options => "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string :key
t.text :value
end
add_index :settings, :key, :unique => true
end
 
def self.down
drop_table :settings
end
end
setting.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
class Setting < ActiveRecord::Base
serialize :value
class << self
attr_accessor :__cache
attr_accessor :__cache_expires_in
end
def self.method_missing(method, *args)
# init memcache if needed
@__cache = ActiveSupport::Cache::MemCacheStore.new if @__cache.nil?
@__cache_expires_in = 6.hours if @__cache_expires_in.nil?
method = method.to_s
# set mode
if method[-1,1] == "="
if args.size > 0
# key/value setup
method = method.chop
method = method.chop if method[-1,1] == "!"
value = {:value => args[0]}
@__cache.write(method, value, :expires_in => @__cache_expires_in)
setting = self.find(:first, :conditions => {:key => method})
if value[:value].nil?
setting.destroy if setting
@__cache.write(method, nil, :expires_in => 0.seconds)
else
setting = self.new if !setting
setting.key = method.to_s if setting.key.blank?
setting.value = value
if setting.save
return value[:value]
end
end
end
# get mode
else
# skip memcache?
if method[-1,1] == "!"
method = method.chop
skip_cache = true
end
if skip_cache.nil? && (result = @__cache.read(method.to_s))
return result[:value]
else
result = self.find(:first, :conditions => {:key => method})
if result
@__cache.write(method, result.value, :expires_in => @__cache_expires_in)
return result.value[:value]
end
end
end
return nil
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.