diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2013-05-06 18:52:57 -0700 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2013-05-06 18:52:57 -0700 |
commit | 33283c98ed690b12bc2bca75276236dc907798b2 (patch) | |
tree | 8c3106531a93af1114e209bb94b5d8a2cbcef4f4 /activesupport | |
parent | 925728c283f2d6f8f41bf79f6958494f14560aeb (diff) | |
parent | 36d41a15c35e6f4b698931987b2115e221d0fcfa (diff) | |
download | rails-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
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/CHANGELOG.md | 14 | ||||
-rw-r--r-- | activesupport/lib/active_support/cache.rb | 28 | ||||
-rw-r--r-- | activesupport/test/caching_test.rb | 20 |
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') |