Created
March 22, 2014 13:21
-
-
Save loicginoux/9707001 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
########################################## | |
# 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