Skip to content

Instantly share code, notes, and snippets.

@loicginoux
Created March 22, 2014 13:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loicginoux/9707001 to your computer and use it in GitHub Desktop.
Save loicginoux/9707001 to your computer and use it in GitHub Desktop.
##########################################
# Use cases:
# setting a config variable: Variable[:my_key] = 1
# getting a config variable: Variable[:my_key]
# retrieving all keys: Variable.keys
# deleting a key: Variable.delete!(:my_key)
# checking existence: Variable.exists?(:my_key)
# clear all keys: Variable.clear!
#
# Values are transformed to yaml before stored
# this allows you to store any type of object
# string, integer, boolean, hashes or more complicated objects
#
# In a real application I would also add an initializer
# that inject in the table the default variables
# from a file config/default_global_variables.yml
#
# Another thing that could be done is removing the
# primary key :id and set the primary key on the column :key.
# I didn't because my test db was SQLite and I had this problem:
# http://stackoverflow.com/questions/946011/sqlite-add-primary-key
# But with another DB it would be better to have something like this
# in migration file:
#
# create_table :variables, :id => false do |t|
# t.string "key", :unique => true, :null => false
# t.text "value"
# end
# execute "ALTER TABLE variables ADD PRIMARY KEY (key);"
#
# and adding in your model this line:
# set_primary_key :key
#
##########################################
# migration file
class CreateVariable < ActiveRecord::Migration
def change
create_table :configs do |t|
t.string "key", :limit => 30, :default => "", :null => false
t.text "value"
end
add_index :configs, :key, :unique => true
end
end
# lib/errors.rb
module Errors
# used when we try to retrieve a nil key
class VariableNilKeyError < StandardError; end
end
# app/models/variable.rb
class Variable < ActiveRecord::Base
validates_uniqueness_of :key
def self.[](key)
key = key.to_s
return Rails.cache.read(key) if Rails.cache.exist?(key)
entry = Variable.find_by(key: key)
entry ? YAML.load(entry.value) : nil
end
def self.[]=(key, value)
raise Errors::VariableNilKeyError if key.nil?
key = key.to_s
entry = Variable.find_or_create_by(key: key)
entry.value = value.to_yaml
Rails.cache.write(key, value)
entry.save
entry.value
end
def self.keys
self.all.map(&:key).map(&:to_sym)
end
def self.delete!(key)
Rails.cache.delete(key)
Variable.delete_all(:key => key)
end
def self.exists?(key)
!self[key].nil?
end
def self.clear!
# Variable.destroy_all is not enough
# as the value in cache will stay
self.keys.each { |k| self.delete!(k) }
end
end
# spec/models/variable_spec.rb
require 'spec_helper'
describe Variable do
it 'should save a new key and value without failing' do
proc { Variable[:key_one] = "Key One"}.should_not raise_error
end
it 'should retrieve a value' do
Variable[:my_key] = "my value"
Variable[:my_key].should == "my value"
end
describe ".exists?" do
it 'should check for non existance' do
Variable.exists?(:non_existant).should be_false
end
it 'should check for existance' do
Variable[:existant] = 109
Variable.exists?(:existant).should be_true
end
end
describe ".delete" do
it 'should delete a key and value' do
Variable[:delete_me] = 1098
Variable.exists?(:delete_me).should be_true
Variable.delete!(:delete_me).should be_true
Variable.exists?(:delete_me).should be_false
end
it 'should not throw an error when deleting a key that does not exist' do
proc { Variable.delete!(:non_existant) }.should_not raise_error
end
end
it 'should list all keys' do
Variable[:k1] = 1
Variable[:k2] = 2
Variable[:k3] = 3
Variable.keys.should == [:k1, :k2, :k3]
end
it 'should clear the table' do
Variable[:k1] = 1
Variable[:k2] = 2
Variable[:k3] = 3
Variable.clear!
Variable.keys.should be_empty
end
it 'should fail if a nil key is set' do
proc { Variable[nil] = 1 }.should raise_error(Errors::VariableNilKeyError)
end
it 'should return nil if we get a nil key' do
Variable[nil].should be_nil
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment