module RedisFixtures
Add fixtures to your Redis database, to test the parts of your code that need Redis to be more than a cache.
Constants
- VERSION
Public Class Methods
Cleans up the Redis DB. Call this before starting your sample data generation to start with a clean slate
# File lib/redis_fixtures/dump_fixtures.rb, line 4 def self.before_fixture_data_generation with_redis_connection do |redis| redis.flushdb end end
Returns the current configuration @return [Configuration] the configuration class
# File lib/redis_fixtures/config.rb, line 42 def self.configuration @configuration ||= Configuration.new end
Yields the current configuration, allowing the caller to modify it in a block
# File lib/redis_fixtures/config.rb, line 47 def self.configure yield(configuration) if block_given? end
Path to the file where we’ll store Redis fixtures @return [String]
# File lib/redis_fixtures/config.rb, line 53 def self.fixture_file_path fixtures_dir(RedisFixtures.configuration.fixture_filename) end
Load the Redis fixture YAML file, into Redis, flushing the DB first
# File lib/redis_fixtures/load_fixtures.rb, line 3 def self.load_fixtures return unless File.exists?(fixture_file_path) commands = YAML.load_file(fixture_file_path) with_redis_connection do |redis| redis.pipelined do |predis| predis.flushdb commands.each do |command| predis.send(*command) end end end end
Dumps the contents of the Redis DB into a fixture file. Call this after generating all your sample data in Redis.
# File lib/redis_fixtures/dump_fixtures.rb, line 12 def self.save_fixtures redis_dump = with_redis_connection do |redis| dump_keys(redis) end FileUtils.mkdir_p(fixtures_dir) unless File.directory?(fixtures_dir) File.open(fixture_file_path, 'w') { |file| file.write(redis_dump.to_yaml) } end
Gets a connection to Redis using whatever method was configured, and yields it to the block passed in @return [Object] Whatever your block returned
# File lib/redis_fixtures/connection.rb, line 5 def self.with_redis_connection result = nil conf = RedisFixtures.configuration if conf.connection_pool.present? conf.connection_pool.with do |redis| result = yield(redis) end elsif conf.connection.present? result = yield(conf.connection) elsif conf.connection_proc.present? || conf.connection_settings.present? redis = conf.connection_proc.present? ? conf.connection_proc.call : Redis.new(conf.connection_settings) result = yield(redis) redis.disconnect! if redis.respond_to?(:disconnect!) end result end
Private Class Methods
Dump a Redis Hash into a ‘command` that will allows us to regenerate it @param redis [Redis] Redis connection @param key [String] the key to dump @return [Array] an array specifying a `mapped_hmset` command, the key, and the hash to store in Redis
# File lib/redis_fixtures/dump_fixtures.rb, line 53 def self.dump_hash(redis, key) hash = redis.hgetall(key) [:mapped_hmset, key, hash] end
Finds all the keys in the Redis Database and dumps them into an array of arrays that can then be used to easily reconstruct the data
@param redis [Redis] Redis connection @return [Array of ‘commands`] an array of arrays, one entry per key, each of which can be used to execute a redis call that will create and populate the key in Redis.
# File lib/redis_fixtures/dump_fixtures.rb, line 28 def self.dump_keys(redis) keys = redis.keys("*") keys.map do |key| key_type = redis.type(key) case key_type when "hash" dump_hash(redis, key) when "zset" dump_zset(redis, key) when "list" dump_list(redis, key) when "set" dump_set(redis, key) when "string" # HLL's are stored internally as strings dump_string(redis, key) else raise "Don't know how to dump a fixture for Redis type: #{key_type} (key: #{key})" # Should never happen, these are all the types Redis can return end end end
Dump a Redis List into a ‘command` that will allows us to regenerate it @param redis [Redis] Redis connection @param key [String] the key to dump @return [Array] an array specifying a `rpush` command, the key, and the values and scores to store in Redis
# File lib/redis_fixtures/dump_fixtures.rb, line 72 def self.dump_list(redis, key) list = redis.lrange key, 0, -1 [:rpush, key, list] end
Dump a Redis Set into a ‘command` that will allows us to regenerate it @param redis [Redis] Redis connection @param key [String] the key to dump @return [Array] an array specifying a `sadd` command, the key, and the values and scores to store in Redis
# File lib/redis_fixtures/dump_fixtures.rb, line 81 def self.dump_set(redis, key) set = redis.smembers key [:sadd, key, set] end
Dump a Redis String into a ‘command` that will allows us to regenerate it This also covers HyperLogLogs and Bitmaps. @param redis [Redis] Redis connection @param key [String] the key to dump @return [Array] an array specifying a `set` command, the key, and the string to store in Redis
# File lib/redis_fixtures/dump_fixtures.rb, line 91 def self.dump_string(redis, key) [:set, key, redis.get(key)] end
Dump a Redis Sorted Set into a ‘command` that will allows us to regenerate it @param redis [Redis] Redis connection @param key [String] the key to dump @return [Array] an array specifying a `zadd` command, the key, and the values and scores to store in Redis
# File lib/redis_fixtures/dump_fixtures.rb, line 62 def self.dump_zset(redis, key) zset = redis.zrange key, 0, -1, with_scores: true zset = zset.map{|entry| entry.reverse} # Zrange returns [["a", 32.0], ["b", 64.0]]. Zadd wants [[32.0, "a"], [64.0, "b"]] [:zadd, key, zset] end
Full path to where Fixtures are stored, or to a file inside the fixtures directory @param path [Symbol] path to resolve inside of the fixtures directory @return [String] “{your_app}/(spec|test)/fixtures/{path}”
# File lib/redis_fixtures/config.rb, line 62 def self.fixtures_dir(path = '') File.expand_path(File.join(RedisFixtures.configuration.app_root, spec_or_test_dir, 'fixtures', path)) end
Directory where specs or tests are stored @return [String] ‘spec’ or ‘test’
# File lib/redis_fixtures/config.rb, line 68 def self.spec_or_test_dir File.exists?(File.join(RedisFixtures.configuration.app_root, 'spec')) ? 'spec' : 'test' end