aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Mendonça França <rafaelmfranca@gmail.com>2013-05-06 18:52:57 -0700
committerRafael Mendonça França <rafaelmfranca@gmail.com>2013-05-06 18:52:57 -0700
commit33283c98ed690b12bc2bca75276236dc907798b2 (patch)
tree8c3106531a93af1114e209bb94b5d8a2cbcef4f4
parent925728c283f2d6f8f41bf79f6958494f14560aeb (diff)
parent36d41a15c35e6f4b698931987b2115e221d0fcfa (diff)
downloadrails-33283c98ed690b12bc2bca75276236dc907798b2.tar.gz
rails-33283c98ed690b12bc2bca75276236dc907798b2.tar.bz2
rails-33283c98ed690b12bc2bca75276236dc907798b2.zip
Merge pull request #10234 from dasch/dasch/fetch-multi
Allow fetching multiple values from the cache at once
-rw-r--r--activesupport/CHANGELOG.md14
-rw-r--r--activesupport/lib/active_support/cache.rb28
-rw-r--r--activesupport/test/caching_test.rb20
3 files changed, 61 insertions, 1 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 7f2e776825..8819a4e373 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,15 @@
-* No changes.
+* Add a `fetch_multi` method to the cache stores. The method provides
+ an easy to use API for fetching multiple values from the cache.
+
+ Example:
+
+ # Calculating scores is expensive, so we only do it for posts
+ # that have been updated. Cache keys are automatically extracted
+ # from objects that define a #cache_key method.
+ scores = Rails.cache.fetch_multi(*posts) do |post|
+ calculate_score(post)
+ end
+
+ *Daniel Schierbeck*
Please check [4-0-stable](https://github.com/rails/rails/blob/4-0-stable/activesupport/CHANGELOG.md) for previous changes.
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 6c220ae625..b1ab5570a8 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -352,6 +352,34 @@ module ActiveSupport
results
end
+ # Fetches data from the cache, using the given keys. If there is data in
+ # the cache with the given keys, then that data is returned. Otherwise,
+ # the supplied block is called for each key for which there was no data,
+ # and the result will be written to the cache and returned.
+ #
+ # Options are passed to the underlying cache implementation.
+ #
+ # Returns an array with the data for each of the names. For example:
+ #
+ # cache.write("bim", "bam")
+ # cache.fetch_multi("bim", "boom") {|key| key * 2 }
+ # #=> ["bam", "boomboom"]
+ #
+ def fetch_multi(*names)
+ options = names.extract_options!
+ options = merged_options(options)
+
+ results = read_multi(*names, options)
+
+ names.map do |name|
+ results.fetch(name) do
+ value = yield name
+ write(name, value, options)
+ value
+ end
+ end
+ end
+
# Writes the value to the cache, with the key.
#
# Options are passed to the underlying cache implementation.
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index bcc200cf33..ae6eaa4b60 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -257,6 +257,26 @@ module CacheStoreBehavior
assert_equal({"fu" => "baz"}, @cache.read_multi('foo', 'fu'))
end
+ def test_fetch_multi
+ @cache.write('foo', 'bar')
+ @cache.write('fud', 'biz')
+
+ values = @cache.fetch_multi('foo', 'fu', 'fud') {|value| value * 2 }
+
+ assert_equal(["bar", "fufu", "biz"], values)
+ assert_equal("fufu", @cache.read('fu'))
+ end
+
+ def test_multi_with_objects
+ foo = stub(:title => "FOO!", :cache_key => "foo")
+ bar = stub(:cache_key => "bar")
+
+ @cache.write('bar', "BAM!")
+
+ values = @cache.fetch_multi(foo, bar) {|object| object.title }
+ assert_equal(["FOO!", "BAM!"], values)
+ end
+
def test_read_and_write_compressed_small_data
@cache.write('foo', 'bar', :compress => true)
assert_equal 'bar', @cache.read('foo')