Skip to content
This repository was archived by the owner on Mar 15, 2022. It is now read-only.

Commit aed23e8

Browse files
committed
Add TS::Cache#fetch_or_store.
The method is going to have semantics identical to those provided by Rails.cache#fetch.
1 parent 11a0047 commit aed23e8

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

lib/thread_safe/cache.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,13 @@ def fetch(key, default_value = NULL)
5959
elsif NULL != default_value
6060
default_value
6161
else
62-
raise KEY_ERROR, 'key not found'
62+
raise_fetch_no_key
63+
end
64+
end
65+
66+
def fetch_or_store(key, default_value = NULL)
67+
fetch(key) do
68+
put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value))
6369
end
6470
end
6571

@@ -131,6 +137,10 @@ def marshal_load(hash)
131137
undef :freeze
132138

133139
private
140+
def raise_fetch_no_key
141+
raise KEY_ERROR, 'key not found'
142+
end
143+
134144
def initialize_copy(other)
135145
super
136146
populate_from(other)

test/test_cache.rb

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,11 @@ def test_fetch
470470
assert_raises(ThreadSafe::Cache::KEY_ERROR) do
471471
@cache.fetch(:b)
472472
end
473+
474+
assert_no_size_change do
475+
assert_equal 1, (@cache.fetch(:b, :c) {1}) # assert block supersedes default value argument
476+
assert_equal false, @cache.key?(:b)
477+
end
473478
end
474479
end
475480

@@ -505,6 +510,86 @@ def test_fetch_with_return
505510
end
506511
end
507512

513+
def test_fetch_or_store
514+
with_or_without_default_proc do |default_proc_set|
515+
assert_size_change 1 do
516+
assert_equal 1, @cache.fetch_or_store(:a, 1)
517+
assert_equal 1, @cache[:a]
518+
end
519+
520+
@cache.delete(:a)
521+
522+
assert_size_change 1 do
523+
assert_equal 1, (@cache.fetch_or_store(:a) {1})
524+
assert_equal 1, @cache[:a]
525+
end
526+
527+
assert_no_size_change do
528+
assert_equal(1, (@cache.fetch_or_store(:a) {flunk}))
529+
end
530+
531+
assert_raises(ThreadSafe::Cache::KEY_ERROR) do
532+
@cache.fetch_or_store(:b)
533+
end
534+
535+
assert_size_change 1 do
536+
assert_equal 1, (@cache.fetch_or_store(:b, :c) {1}) # assert block supersedes default value argument
537+
assert_equal 1, @cache[:b]
538+
end
539+
end
540+
end
541+
542+
def test_falsy_fetch_or_store
543+
with_or_without_default_proc do
544+
assert_equal false, @cache.key?(:a)
545+
546+
assert_size_change 1 do
547+
assert_equal(nil, @cache.fetch_or_store(:a, nil))
548+
assert_equal nil, @cache[:a]
549+
assert_equal true, @cache.key?(:a)
550+
end
551+
@cache.delete(:a)
552+
553+
assert_size_change 1 do
554+
assert_equal(false, @cache.fetch_or_store(:a, false))
555+
assert_equal false, @cache[:a]
556+
assert_equal true, @cache.key?(:a)
557+
end
558+
@cache.delete(:a)
559+
560+
assert_size_change 1 do
561+
assert_equal(nil, (@cache.fetch_or_store(:a) {}))
562+
assert_equal nil, @cache[:a]
563+
assert_equal true, @cache.key?(:a)
564+
end
565+
@cache.delete(:a)
566+
567+
assert_size_change 1 do
568+
assert_equal(false, (@cache.fetch_or_store(:a) {false}))
569+
assert_equal false, @cache[:a]
570+
assert_equal true, @cache.key?(:a)
571+
end
572+
573+
@cache[:a] = nil
574+
assert_no_size_change do
575+
assert_equal(nil, (@cache.fetch_or_store(:a) {flunk}))
576+
end
577+
end
578+
end
579+
580+
def test_fetch_or_store_with_return
581+
with_or_without_default_proc do
582+
r = lambda do
583+
@cache.fetch_or_store(:a) { return 10 }
584+
end.call
585+
586+
assert_no_size_change do
587+
assert_equal 10, r
588+
assert_equal false, @cache.key?(:a)
589+
end
590+
end
591+
end
592+
508593
def test_clear
509594
@cache[:a] = 1
510595
assert_size_change -1 do

0 commit comments

Comments
 (0)