$ ruby run.rb
Test 0: error: #<NoMethodError: undefined method `<=' for nil:NilClass>
Test 1: fail
Test 2: success
Test 3: fail
Test 4: error: #<NoMethodError: undefined method `<=' for nil:NilClass>
Test 5: success
Test 6: success
Test 7: success
Test 8: success
-
-
Save mariusbutuc/3acebc6b58361a0b8686be46f851f014 to your computer and use it in GitHub Desktop.
Code Kata #4: Cache
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 Cache | |
attr_accessor :data | |
def initialize(data: {}) | |
@data = data | |
end | |
def get(key) | |
return if data.fetch(key, {}).fetch(:expires_at, nil) <= now | |
value_for(key) | |
end | |
def set(key, value, expires_at: default_expires_at) | |
data[key] = { value: value, expires_at: expires_at } | |
end | |
def delete(key) | |
data.delete(key) | |
end | |
def fetch(key, &block) | |
value = value_for(key) | |
data[key] = { value: yield, expires_at: default_expires_at } if value.nil? | |
value_for(key) | |
end | |
private | |
def now | |
# timezones? UTC? | |
Time.now | |
end | |
def default_expires_at | |
now + 100 | |
end | |
def value_for(key) | |
data.fetch(key, {}).fetch(:value, nil) | |
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 './cache.rb' | |
cache = Cache.new | |
tests = [ | |
# 0 | |
Proc.new do |cache| | |
cache.get(:foo).nil? | |
end, | |
# 1 | |
Proc.new do |cache| | |
cache.set(:foo, 'FOO') == 'FOO' | |
end, | |
# 2 | |
Proc.new do |cache| | |
cache.set(:foo, 'FOO') | |
cache.get(:foo) == 'FOO' | |
end, | |
# 3 | |
Proc.new do |cache| | |
cache.set(:foo, 'FOO') | |
cache.delete(:foo) == 'FOO' | |
end, | |
# 4 | |
Proc.new do |cache| | |
cache.set(:foo, 'FOO') | |
cache.delete(:foo) | |
cache.get(:foo).nil? | |
end, | |
# 5 | |
Proc.new do |cache| | |
num_calls = 0 | |
calculation = -> { num_calls += 1 } | |
cache.fetch(:foo, &calculation) == 1 && cache.fetch(:foo, &calculation) == 1 | |
end, | |
# 6 | |
Proc.new do |cache| | |
now = Time.now | |
expires_at = now + 100 | |
cache.set(:foo, 'FOO', expires_at: expires_at) | |
cache.get(:foo) == 'FOO' | |
end, | |
# 7 | |
Proc.new do |cache| | |
now = Time.now | |
expires_at = now - 1 | |
cache.set(:foo, 'FOO', expires_at: expires_at) | |
cache.get(:foo).nil? | |
end, | |
# 8 | |
Proc.new do |cache| | |
now = Time.now | |
expires_at = now + 1 | |
cache.set(:foo, 'FOO', expires_at: expires_at) | |
sleep(1.2) | |
cache.get(:foo).nil? | |
end, | |
] | |
tests.each_with_index do |test, i| | |
cache = Cache.new | |
print "Test #{i}: " | |
begin | |
if test.call(cache) | |
puts 'success' | |
else | |
puts 'fail' | |
end | |
rescue StandardError => exception | |
puts "error: #{exception.inspect}" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment