Add ActiveSupport::Cache::NullStore to expose caching interface without actually caching for development and test environments.

This commit is contained in:
Brian Durand 2011-12-12 13:40:29 -06:00
parent 2fdc3ab0f1
commit 04d5eae4e8
6 changed files with 123 additions and 8 deletions

View File

@ -146,6 +146,10 @@
during :reject_if => :all_blank (fixes #2937) during :reject_if => :all_blank (fixes #2937)
*Aaron Christy* *Aaron Christy*
* Add ActiveSupport::Cache::NullStore for use in development and testing.
*Brian Durand*
## Rails 3.1.3 (unreleased) ## ## Rails 3.1.3 (unreleased) ##

View File

@ -16,6 +16,7 @@ module ActiveSupport
autoload :FileStore, 'active_support/cache/file_store' autoload :FileStore, 'active_support/cache/file_store'
autoload :MemoryStore, 'active_support/cache/memory_store' autoload :MemoryStore, 'active_support/cache/memory_store'
autoload :MemCacheStore, 'active_support/cache/mem_cache_store' autoload :MemCacheStore, 'active_support/cache/mem_cache_store'
autoload :NullStore, 'active_support/cache/null_store'
# These options mean something to all cache implementations. Individual cache # These options mean something to all cache implementations. Individual cache
# implementations may support additional options. # implementations may support additional options.

View File

@ -0,0 +1,44 @@
module ActiveSupport
module Cache
# A cache store implementation which doesn't actually store anything. Useful in
# development and test environments where you don't want caching turned on but
# need to go through the caching interface.
#
# This cache does implement the local cache strategy, so values will actually
# be cached inside blocks that utilize this strategy. See
# ActiveSupport::Cache::Strategy::LocalCache for more details.
class NullStore < Store
def initialize(options = nil)
super(options)
extend Strategy::LocalCache
end
def clear(options = nil)
end
def cleanup(options = nil)
end
def increment(name, amount = 1, options = nil)
end
def decrement(name, amount = 1, options = nil)
end
def delete_matched(matcher, options = nil)
end
protected
def read_entry(key, options) # :nodoc:
end
def write_entry(key, entry, options) # :nodoc:
true
end
def delete_entry(key, options) # :nodoc:
false
end
end
end
end

View File

@ -218,7 +218,7 @@ module CacheStoreBehavior
@cache.write('fud', 'biz') @cache.write('fud', 'biz')
assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu')) assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu'))
end end
def test_read_multi_with_expires def test_read_multi_with_expires
@cache.write('foo', 'bar', :expires_in => 0.001) @cache.write('foo', 'bar', :expires_in => 0.001)
@cache.write('fu', 'baz') @cache.write('fu', 'baz')
@ -576,12 +576,12 @@ class FileStoreTest < ActiveSupport::TestCase
key = @cache_with_pathname.send(:key_file_path, "views/index?id=1") key = @cache_with_pathname.send(:key_file_path, "views/index?id=1")
assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key) assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key)
end end
# Because file systems have a maximum filename size, filenames > max size should be split in to directories # Because file systems have a maximum filename size, filenames > max size should be split in to directories
# If filename is 'AAAAB', where max size is 4, the returned path should be AAAA/B # If filename is 'AAAAB', where max size is 4, the returned path should be AAAA/B
def test_key_transformation_max_filename_size def test_key_transformation_max_filename_size
key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}B" key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}B"
path = @cache.send(:key_file_path, key) path = @cache.send(:key_file_path, key)
assert path.split('/').all? { |dir_name| dir_name.size <= ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE} assert path.split('/').all? { |dir_name| dir_name.size <= ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}
assert_equal 'B', File.basename(path) assert_equal 'B', File.basename(path)
end end
@ -689,14 +689,14 @@ uses_memcached 'memcached backed store' do
cache.write("foo", 2) cache.write("foo", 2)
assert_equal "2", cache.read("foo") assert_equal "2", cache.read("foo")
end end
def test_raw_values_with_marshal def test_raw_values_with_marshal
cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, :raw => true) cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, :raw => true)
cache.clear cache.clear
cache.write("foo", Marshal.dump([])) cache.write("foo", Marshal.dump([]))
assert_equal [], cache.read("foo") assert_equal [], cache.read("foo")
end end
def test_local_cache_raw_values def test_local_cache_raw_values
cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, :raw => true) cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, :raw => true)
cache.clear cache.clear
@ -717,6 +717,64 @@ uses_memcached 'memcached backed store' do
end end
end end
class NullStoreTest < ActiveSupport::TestCase
def setup
@cache = ActiveSupport::Cache.lookup_store(:null_store)
end
def test_clear
@cache.clear
end
def test_cleanup
@cache.cleanup
end
def test_write
assert_equal true, @cache.write("name", "value")
end
def test_read
@cache.write("name", "value")
assert_nil @cache.read("name")
end
def test_delete
@cache.write("name", "value")
assert_equal false, @cache.delete("name")
end
def test_increment
@cache.write("name", 1, :raw => true)
assert_nil @cache.increment("name")
end
def test_decrement
@cache.write("name", 1, :raw => true)
assert_nil @cache.increment("name")
end
def test_delete_matched
@cache.write("name", "value")
@cache.delete_matched(/name/)
end
def test_local_store_strategy
@cache.with_local_cache do
@cache.write("name", "value")
assert_equal "value", @cache.read("name")
@cache.delete("name")
assert_nil @cache.read("name")
@cache.write("name", "value")
end
assert_nil @cache.read("name")
end
def test_setting_nil_cache_store
assert ActiveSupport::Cache.lookup_store.class.name, ActiveSupport::Cache::NullStore.name
end
end
class CacheStoreLoggerTest < ActiveSupport::TestCase class CacheStoreLoggerTest < ActiveSupport::TestCase
def setup def setup
@cache = ActiveSupport::Cache.lookup_store(:memory_store) @cache = ActiveSupport::Cache.lookup_store(:memory_store)

View File

@ -332,6 +332,14 @@ caches_action :index, :expires_in => 60.seconds, :unless_exist => true
For more information about Ehcache, see "http://ehcache.org/":http://ehcache.org/ . For more information about Ehcache, see "http://ehcache.org/":http://ehcache.org/ .
For more information about Ehcache for JRuby and Rails, see "http://ehcache.org/documentation/jruby.html":http://ehcache.org/documentation/jruby.html For more information about Ehcache for JRuby and Rails, see "http://ehcache.org/documentation/jruby.html":http://ehcache.org/documentation/jruby.html
h4. ActiveSupport::Cache::NullStore
This cache store implementation is meant to be used only in development or test environments and it never stores anything. This can be very useful in development when you have code that interacts directly with +Rails.cache+, but caching may interfere with being able to see the results of code changes. With this cache store, all +fetch+ and +read+ operations will result in a miss.
<ruby>
ActionController::Base.cache_store = :null
</ruby>
h4. Custom Cache Stores h4. Custom Cache Stores
You can create your own custom cache store by simply extending +ActiveSupport::Cache::Store+ and implementing the appropriate methods. In this way, you can swap in any number of caching technologies into your Rails application. You can create your own custom cache store by simply extending +ActiveSupport::Cache::Store+ and implementing the appropriate methods. In this way, you can swap in any number of caching technologies into your Rails application.

View File

@ -54,9 +54,9 @@ module ApplicationTests
def test_cache_keeps_if_modified_since def test_cache_keeps_if_modified_since
simple_controller simple_controller
expected = "Wed, 30 May 1984 19:43:31 GMT" expected = "Wed, 30 May 1984 19:43:31 GMT"
get "/expires/keeps_if_modified_since", {}, "HTTP_IF_MODIFIED_SINCE" => expected get "/expires/keeps_if_modified_since", {}, "HTTP_IF_MODIFIED_SINCE" => expected
assert_equal 200, last_response.status assert_equal 200, last_response.status
assert_equal expected, last_response.body, "cache should have kept If-Modified-Since" assert_equal expected, last_response.body, "cache should have kept If-Modified-Since"
end end