Skip to content
Browse files

Playing around with adapter for storing state in RDBMS (using ActiveR…

…ecord).
  • Loading branch information...
1 parent 5891c80 commit 9f688e00a06b8672037d4b2b43515ab68827ac57 @assaf assaf committed Dec 21, 2009
Showing with 139 additions and 4 deletions.
  1. +11 −2 lib/vanity/playground.rb
  2. +106 −0 lib/vanity/store/activerecord.rb
  3. +22 −2 test/test_helper.rb
View
13 lib/vanity/playground.rb
@@ -11,14 +11,23 @@ class Playground
# Created new Playground. Unless you need to, use the global Vanity.playground.
def initialize(options = {})
- @host, @port, @db, @load_path = DEFAULTS.merge(options).values_at(:host, :port, :db, :load_path)
+ options = options.merge(DEFAULTS)
+ adapter = options[:adapter] || options[:redis] || :redis
+ if adapter.respond_to?(:mget)
+ @redis = adapter
+ elsif adapter == :redis
+ @host, @port, @db = options.values_at(:host, :port, :db)
+ else
+ require "vanity/store/#{adapter}"
+ @redis = Vanity::Store.const_get(adapter.to_s.capitalize).new
+ end
+ @load_path = options[:load_path]
@namespace = "vanity:#{Vanity::Version::MAJOR}"
@logger = options[:logger]
unless @logger
@logger = Logger.new(STDOUT)
@logger.level = Logger::ERROR
end
- @redis = options[:redis]
@loading = []
end
View
106 lib/vanity/store/activerecord.rb
@@ -0,0 +1,106 @@
+module Vanity
+ module Store
+ # @since 1.3.0
+ class ActiveRecord
+ def initialize(connection = nil)
+ @connection = connection
+ end
+
+ def connection
+ @connection ||= ::ActiveRecord::Base.connection
+ end
+
+ def table_name
+ @table_name ||= "vanity_hash"
+ end
+
+ def get(key)
+ select_value("SELECT value FROM #{table_name} WHERE key=?", key)
+ end
+ alias :[] :get
+
+ def setnx(key, value)
+ execute "INSERT INTO #{table_name} (key, value) VALUES (?,?)", key, value rescue nil
+ end
+
+ def set(key, value)
+ execute("INSERT INTO #{table_name} (key, value) VALUES (?,?)", key, value) rescue
+ execute("UPDATE #{table_name} SET value=? WHERE key=?", value, key)
+ end
+ alias :[]= :set
+
+ def del(*keys)
+ execute "DELETE FROM #{table_name} WHERE key IN (?)", keys.flatten
+ end
+
+ def incrby(key, incr)
+ if value = get(key)
+ execute("UPDATE #{table_name} SET value=? WHERE key=?", value.to_i + incr, key) or incrby(key, incr)
+ else
+ execute("INSERT INTO #{table_name} (key, value) VALUES (?,?)", key, incr) or incrby(key, incr)
+ end
+ end
+
+ def incr(key)
+ incrby key, 1
+ end
+
+ def mget(keys)
+ hash = select_rows("SELECT key, value FROM #{table_name} WHERE key IN (?)", keys).
+ inject({}) { |hash, (key, value)| hash.update(key=>value) }
+ keys.map { |key| hash[key] }
+ end
+
+ def exists(key)
+ select_value("SELECT 1 FROM #{table_name} WHERE key = ?", key) && true
+ end
+
+ def keys(pattern)
+ select_values("SELECT key FROM #{table_name} WHERE key LIKE ?", pattern.gsub("*", "%"))
+ end
+
+ def flushdb
+ execute "DELETE FROM #{table_name}"
+ end
+
+ def sismember(key, value)
+ y = get(key)
+ y ? YAML.load(y).member?(value.to_s) : false
+ end
+
+ def sadd(key, value)
+ y = get(key)
+ s = Set.new(y ? YAML.load(y) : [])
+ s.add value.to_s
+ set key, YAML.dump(s.to_a)
+ end
+
+ def scard(key)
+ y = get(key)
+ y ? YAML.load(y).size : 0
+ end
+ protected
+
+ def bind(statement, *args)
+ ::ActiveRecord::Base.send(:sanitize_sql_array, [statement] + args)
+ end
+
+ def select_value(statement, *args)
+ connection.select_value(bind(statement, *args))
+ end
+
+ def select_values(statement, *args)
+ connection.select_values(bind(statement, *args))
+ end
+
+ def select_rows(statement, *args)
+ connection.select_rows(bind(statement, *args))
+ end
+
+ def execute(statement, *args)
+ connection.execute bind(statement, *args)
+ end
+
+ end
+ end
+end
View
24 test/test_helper.rb
@@ -19,6 +19,27 @@
$logger = Logger.new("/dev/null")
end
+
+case store = ENV["STORE"]
+when "REDIS"
+ puts "Using real Redis server"
+ $adapter = :redis
+when "AR"
+ puts "Using ActiveRecord store"
+ require "vanity/store/activerecord"
+ $redis = Vanity::Store::ActiveRecord.new
+ $redis.connection.execute "CREATE TABLE vanity_hash (key VARCHAR(255) NOT NULL, value TEXT, PRIMARY KEY('key'))" rescue nil
+ $adapter = :activerecord
+when nil
+ require "vanity/store/mock"
+ $redis = Vanity::Store::Mock.new
+ $adapter = :mock
+else
+ puts "Acceptable values for STORE=[REDIS|AR]"
+ exit!
+end
+
+
class Test::Unit::TestCase
def setup
@@ -36,8 +57,7 @@ def nuke_playground
# Call this if you need a new playground, e.g. to re-define the same experiment,
# or reload an experiment (saved by the previous playground).
def new_playground
- Vanity.playground = Vanity::Playground.new(:logger=>$logger, :load_path=>"tmp/experiments", :db=>15)
- Vanity.playground.mock! unless ENV["REDIS"]
+ Vanity.playground = Vanity::Playground.new(:logger=>$logger, :load_path=>"tmp/experiments", :db=>15, :adapter=>$adapter)
end
# Defines the specified metrics (one or more names). Returns metric, or array

0 comments on commit 9f688e0

Please sign in to comment.
Something went wrong with that request. Please try again.