Skip to content

Instantly share code, notes, and snippets.

@Supernats
Last active August 29, 2015 02:28
Show Gist options
  • Select an option

  • Save Supernats/a598215dd5f544119ca8 to your computer and use it in GitHub Desktop.

Select an option

Save Supernats/a598215dd5f544119ca8 to your computer and use it in GitHub Desktop.
class RedisModel::Base
attr_reader :source, :target
def initialize(source:, target:)
@source = source
@target = target
end
class << self
def all
return [] unless count_at_key > 0
all_at_key.map do |key, value|
key = key
value = value
new(source: key, target: value)
end.flatten
end
def create(source:, target:)
model = new(source: source, target: target)
persist!(model) ? model : false
end
def find(source)
model = find!(source)
rescue RedisModel::RecordNotFoundError
end
def find!(source)
raise RedisModel::RecordNotFoundError unless exists_at_key?(source)
target = fetch_value_at(source)
new(source: source, target: target)
end
def destroy(source)
model = find(source)
return false unless model
!!delete!(model)
end
def destroy!(source)
model = find!(source)
!!delete!(model)
end
def key
raise NotImplementedError
end
private
def all_at_key
$redis.hgetall(key)
end
def count_at_key
$redis.hlen(key)
end
def exists_at_key?(source)
$redis.hexists(key, source)
end
def persist!(model)
$redis.hset(key, model.source, model.target)
end
def delete!(model)
$redis.hdel(key, model.source)
end
def fetch_value_at(source)
$redis.hget(key, source)
end
end
end
require 'test_helper'
require 'minitest/spec'
class RedisModel::BaseTest < ActiveSupport::TestCase
extend Minitest::Spec::DSL
describe "class methods" do
subject { RedisModel::Base }
let(:source) { '1' }
let(:target) { '2' }
before do
RedisModel::Base.stubs(key: "redis_model_base_test_key")
clear_redis_at_key
end
def clear_redis_at_key
$redis.del(key)
end
def create_record_with_source_and_target
$redis.hset(key, source, target)
end
def key
subject.key
end
def presence_at_source?
$redis.hexists(key, source)
end
def value_at_source
$redis.hget(key, source)
end
describe "::all" do
describe "when there are RedisModels at the key" do
before { create_record_with_source_and_target }
it "returns an array of all the RedisModels at the key" do
# This assertion really needs to get better
assert_equal [subject.new(source: source, target: target)].sort.map { |model| [model.target, model.source] },
subject.all.sort.sort.map { |model| [model.target, model.source] }
end
end
describe "when there are no RedisModels at the key" do
it "returns an empty array" do
assert_same_elements [], subject.all
end
end
end
describe "::create" do
describe "when there is an existing RedisModel for the given id" do
before { create_record_with_source_and_target }
it "returns false" do
refute subject.create(source: source, target: target)
end
it "does not change the value at the key" do
subject.create(source: source, target: target)
assert_equal target, value_at_source
end
end
describe "when there is no existing RedisModel for the given id" do
it "returns the new RedisModel" do
assert_instance_of subject, subject.create(source: source, target: target)
end
it "sets the value at the key to the initial rate call two's id" do
subject.create(source: source, target: target)
assert_equal target, value_at_source
end
end
end
describe "::find" do
describe "when there is no RedisModel for the given id" do
it "returns nil" do
assert_nil subject.find(source)
end
end
describe "when there is a RedisModel for the given id" do
before { create_record_with_source_and_target }
it "returns the RedisModel" do
redis_model = subject.find(source)
assert_equal source, redis_model.source
assert_equal target, redis_model.target
end
end
end
describe "::find!" do
describe "when there is no RedisModel for the given id" do
it "raises an error" do
assert_raises RedisModel::RecordNotFoundError do
subject.find!(source)
end
end
end
describe "when there is a RedisModel for the given id" do
before { create_record_with_source_and_target }
it "returns the RedisModel" do
redis_model = subject.find!(source)
assert_equal source, redis_model.source
assert_equal target, redis_model.target
end
end
end
describe "::destroy" do
describe "when there is no RedisModel for the given id" do
it "returns false" do
refute subject.destroy(source)
end
end
describe "when there is a RedisModel for the given id" do
before { create_record_with_source_and_target }
it "returns true" do
assert subject.destroy(source)
end
it "deletes the key" do
subject.destroy(source)
refute presence_at_source?
end
end
end
describe "::destroy!" do
describe "where there is no RedisModel for the given id" do
it "raises an error" do
assert_raises RedisModel::RecordNotFoundError do
subject.destroy!(source)
end
end
end
describe "when there is a RedisModel for the given id" do
before { create_record_with_source_and_target }
it "deletes the key" do
subject.destroy(source)
refute presence_at_source?
end
end
end
describe "::key" do
before { RedisModel::Base.unstub(:key) }
it "must respond to ::key" do
assert_respond_to subject, :key
end
it "relies on subclasses to define their key" do
assert_raises NotImplementedError do
subject.key
end
end
end
end
end
class RedisModel::RecordNotFoundError < StandardError
def message
"There is no record for the key requested."
end
end
@cjavdev
Copy link

cjavdev commented Aug 29, 2015

👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment