Last active
August 29, 2015 02:28
-
-
Save Supernats/a598215dd5f544119ca8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| 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 |
This file contains hidden or 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
| 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 |
This file contains hidden or 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
| class RedisModel::RecordNotFoundError < StandardError | |
| def message | |
| "There is no record for the key requested." | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
👏