sequel-cacheable 0.0.7 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,223 +1,30 @@
1
1
  require 'sequel'
2
- require 'hashr'
3
2
  require 'msgpack'
4
3
 
4
+ require 'sequel-cacheable/version'
5
+ require 'sequel-cacheable/packer'
6
+ require 'sequel-cacheable/driver'
7
+ require 'sequel-cacheable/class_methods'
8
+ require 'sequel-cacheable/instance_methods'
9
+ require 'sequel-cacheable/dataset_methods'
10
+
5
11
  module Sequel::Plugins
6
12
  module Cacheable
7
13
  def self.configure(model, store, options = {})
8
14
  model.instance_eval do
9
- @cache_store = store
10
- @cache_store_type = Hashr.new({
11
- :set_with_ttl => store.respond_to?(:set) ? store.method(:set).arity != 2 : false,
12
- :delete_method => (
13
- (store.respond_to?(:del) && :del) ||
14
- (store.respond_to?(:delete) && :delete) ||
15
- (raise NoMethodError, "#{store.class} is not implemented delete method")
16
- )
17
- })
18
- @cache_options = Hashr.new(options, {
15
+ @cache_options = {
19
16
  :ttl => 3600,
20
- :ignore_exception => false,
21
17
  :pack_lib => MessagePack,
22
- :query_cache => store.respond_to?(:keys)
23
- })
24
- end
25
- end
26
-
27
- module ClassMethods
28
- attr_reader :cache_store
29
- attr_reader :cache_store_type
30
- attr_reader :cache_options
31
-
32
- def inherited(subclass)
33
- super
34
- cache = [@cache_store, @cache_store_type, @cache_options]
35
- subclass.instance_eval do
36
- @cache_store = cache[0]
37
- @cache_store_type = cache[1]
38
- @cache_options = cache[2]
39
- end
40
- end
41
-
42
- def cache_set(key, obj, ttl = nil)
43
- return obj if obj.nil?
44
-
45
- ttl = ttl || cache_options.ttl
46
- if cache_options.pack_lib?
47
- obj = obj.map{|o| o.id } if obj.kind_of?(Array)
48
- obj = cache_options.pack_lib.pack(obj)
49
- end
50
-
51
- args = [key, obj]
52
- args << ttl if cache_store_type.set_with_ttl?
53
- cache_store.set(*args)
54
- unless cache_store_type.set_with_ttl?
55
- cache_store.expire(key, ttl)
56
- end
57
- end
58
-
59
- def cache_get(key)
60
- if cache_options.ignore_exceptions?
61
- obj = cache_store.get(key) rescue nil
62
- else
63
- obj = cache_store.get(key)
64
- end
65
-
66
- if obj && cache_options.pack_lib?
67
- obj = restore_cache(cache_options.pack_lib.unpack(obj))
68
- end
69
-
70
- obj
71
- end
72
-
73
- def cache_mget(*keys)
74
- if cache_options.ignore_exceptions?
75
- objs = cache_store.mget(*keys) rescue nil
76
- else
77
- objs = cache_store.mget(*keys)
78
- end
79
-
80
- if objs && cache_options.pack_lib?
81
- objs.map!{|obj|
82
- key = keys.shift
83
- (obj && restore_cache(cache_options.pack_lib.unpack(obj))) ||
84
- model[key.sub(/^#{model}::/, '')]
85
- }
86
- end
87
-
88
- objs || []
89
- end
90
-
91
- def cache_del(key)
92
- cache_store.send(cache_store_type.delete_method, key)
93
- end
94
-
95
- def cache_set_get(key, ttl = nil)
96
- if (val = cache_get(key)).nil?
97
- val = yield
98
- cache_set(key, val, ttl)
99
- end
100
- val
101
- end
102
-
103
- def restore_cache(object)
104
- return object if object.nil?
105
-
106
- return cache_mget(*object.map{|id| "#{model}::#{id}" }) if object.kind_of?(Array)
107
-
108
- object.keys.each do | key |
109
- value = object.delete(key)
110
- key = key.to_sym rescue key
111
- case db_schema[key][:type]
112
- when :date
113
- value = Date.new(*value)
114
- when :time
115
- value = Sequel::SQLTime.at(value[0], value[1])
116
- when :datetime
117
- value = Time.at(value[0], value[1])
118
- when :decimal
119
- value = BigDecimal.new(value)
120
- when :integer
121
- value = value.to_i
122
- end
123
- object[key] = value
124
- end
125
- new(object, true)
126
- end
127
-
128
- def clear_query_cache
129
- return unless cache_options.query_cache?
130
- cache_store.keys("#{model.name}::Query::*").each do | key |
131
- cache_del(key)
132
- end
133
- end
134
-
135
- def primary_key_lookup(key)
136
- cache_set_get("#{model}::#{key}") do
137
- super(key)
138
- end
139
- end
140
- end
141
-
142
- module InstanceMethods
143
- def msgpack_hash
144
- hash = {}
145
- @values.each_pair do | key, value |
146
- case value
147
- when Date
148
- value = [value.year, value.mon, value.mday, value.start]
149
- when Sequel::SQLTime, Time
150
- value = [value.to_i, value.usec]
151
- when BigDecimal, Bignum
152
- value = value.to_s
153
- end
154
- hash[key] = value
155
- end
156
- hash
157
- end
158
-
159
- def to_msgpack(*args)
160
- msgpack_hash.to_msgpack
161
- end
162
-
163
- def after_initialize
164
- store_cache unless id.nil?
165
- super
166
- end
167
-
168
- def after_update
169
- restore_cache
170
- super
171
- end
172
-
173
- def delete
174
- delete_cache
175
- super
176
- end
177
-
178
- def destroy(*args)
179
- delete_cache
180
- super(*args)
181
- end
182
-
183
- def store_cache
184
- model.cache_set(cache_key, self)
185
- end
186
-
187
- def delete_cache
188
- model.cache_del(cache_key)
189
- model.clear_query_cache
190
- end
191
-
192
- def restore_cache
193
- delete_cache
194
- store_cache
195
- end
196
-
197
- def cache_key
198
- "#{self.class.name}::#{self.id.to_s}"
199
- end
200
- end
201
-
202
- module DatasetMethods
203
- def all(*args)
204
- if model.cache_options.query_cache? && @row_proc.kind_of?(Class) && @row_proc.included_modules.include?(Sequel::Model::InstanceMethods)
205
- @row_proc.cache_set_get(query_to_cache_key) { super(*args) }
206
- else
207
- super(*args)
208
- end
209
- end
210
-
211
- def first(*args)
212
- if model.cache_options.query_cache? && @row_proc.kind_of?(Class) && @row_proc.included_modules.include?(Sequel::Model::InstanceMethods)
213
- @row_proc.cache_set_get(query_to_cache_key) { super(*args) }
214
- else
215
- super(*args)
216
- end
217
- end
218
-
219
- def query_to_cache_key
220
- model.name + '::Query::' + select_sql.gsub(/ /, '_')
18
+ :query_cache => false
19
+ }.merge(options)
20
+ @cache_driver = Driver.factory(
21
+ store,
22
+ Packer.factory(@cache_options[:pack_lib])
23
+ )
24
+ @caches = {
25
+ :instance => [],
26
+ :query => []
27
+ }
221
28
  end
222
29
  end
223
30
  end
@@ -1,98 +1,22 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'sequel-cacheable/version'
5
4
 
6
- Gem::Specification.new do |s|
7
- s.name = "sequel-cacheable"
8
- s.version = "0.0.7"
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "sequel-cacheable"
7
+ gem.version = Sequel::Plugins::Cacheable::VERSION
8
+ gem.authors = ["Sho Kusano"]
9
+ gem.email = ["rosylilly@aduca.org"]
10
+ gem.description = %q{This plug-in caching mechanism to implement the Model of the Sequel}
11
+ gem.summary = %q{This plug-in caching mechanism to implement the Model of the Sequel}
12
+ gem.homepage = "https://github.com/rosylilly/sequel-cacheable"
13
+ gem.license = "MIT"
9
14
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Sho Kusano <rosylilly>"]
12
- s.date = "2012-05-01"
13
- s.description = "This plug-in caching mechanism to implement the Model of the Sequel"
14
- s.email = "rosylilly@aduca.org"
15
- s.extra_rdoc_files = [
16
- "LICENSE.txt",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".document",
21
- ".rspec",
22
- ".travis.yml",
23
- "Gemfile",
24
- "Gemfile.lock",
25
- "Guardfile",
26
- "LICENSE.txt",
27
- "README.rdoc",
28
- "Rakefile",
29
- "VERSION",
30
- "lib/sequel-cacheable.rb",
31
- "sequel-cacheable.gemspec",
32
- "spec/lib/sequel-cacheable_spec.rb",
33
- "spec/spec_helper.rb"
34
- ]
35
- s.homepage = "http://github.com/rosylilly/sequel-cacheable"
36
- s.licenses = ["MIT"]
37
- s.require_paths = ["lib"]
38
- s.rubygems_version = "1.8.22"
39
- s.summary = "This plug-in caching mechanism to implement the Model of the Sequel"
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
40
19
 
41
- if s.respond_to? :specification_version then
42
- s.specification_version = 3
43
-
44
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
- s.add_runtime_dependency(%q<sequel>, ["~> 3.34"])
46
- s.add_runtime_dependency(%q<msgpack>, ["~> 0.4.6"])
47
- s.add_runtime_dependency(%q<hashr>, ["~> 0.0.19"])
48
- s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
49
- s.add_development_dependency(%q<rspec>, ["~> 2"])
50
- s.add_development_dependency(%q<yard>, ["~> 0.7"])
51
- s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
52
- s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
53
- s.add_development_dependency(%q<simplecov>, ["~> 0.6.1"])
54
- s.add_development_dependency(%q<guard>, ["~> 1.0.0"])
55
- s.add_development_dependency(%q<guard-rspec>, ["~> 0.7"])
56
- s.add_development_dependency(%q<growl>, [">= 0"])
57
- s.add_development_dependency(%q<sqlite3>, [">= 0"])
58
- s.add_development_dependency(%q<memcache>, [">= 0"])
59
- s.add_development_dependency(%q<redis>, [">= 0"])
60
- s.add_development_dependency(%q<queencheck>, [">= 0"])
61
- else
62
- s.add_dependency(%q<sequel>, ["~> 3.34"])
63
- s.add_dependency(%q<msgpack>, ["~> 0.4.6"])
64
- s.add_dependency(%q<hashr>, ["~> 0.0.19"])
65
- s.add_dependency(%q<bundler>, [">= 1.0.0"])
66
- s.add_dependency(%q<rspec>, ["~> 2"])
67
- s.add_dependency(%q<yard>, ["~> 0.7"])
68
- s.add_dependency(%q<rdoc>, ["~> 3.12"])
69
- s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
70
- s.add_dependency(%q<simplecov>, ["~> 0.6.1"])
71
- s.add_dependency(%q<guard>, ["~> 1.0.0"])
72
- s.add_dependency(%q<guard-rspec>, ["~> 0.7"])
73
- s.add_dependency(%q<growl>, [">= 0"])
74
- s.add_dependency(%q<sqlite3>, [">= 0"])
75
- s.add_dependency(%q<memcache>, [">= 0"])
76
- s.add_dependency(%q<redis>, [">= 0"])
77
- s.add_dependency(%q<queencheck>, [">= 0"])
78
- end
79
- else
80
- s.add_dependency(%q<sequel>, ["~> 3.34"])
81
- s.add_dependency(%q<msgpack>, ["~> 0.4.6"])
82
- s.add_dependency(%q<hashr>, ["~> 0.0.19"])
83
- s.add_dependency(%q<bundler>, [">= 1.0.0"])
84
- s.add_dependency(%q<rspec>, ["~> 2"])
85
- s.add_dependency(%q<yard>, ["~> 0.7"])
86
- s.add_dependency(%q<rdoc>, ["~> 3.12"])
87
- s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
88
- s.add_dependency(%q<simplecov>, ["~> 0.6.1"])
89
- s.add_dependency(%q<guard>, ["~> 1.0.0"])
90
- s.add_dependency(%q<guard-rspec>, ["~> 0.7"])
91
- s.add_dependency(%q<growl>, [">= 0"])
92
- s.add_dependency(%q<sqlite3>, [">= 0"])
93
- s.add_dependency(%q<memcache>, [">= 0"])
94
- s.add_dependency(%q<redis>, [">= 0"])
95
- s.add_dependency(%q<queencheck>, [">= 0"])
96
- end
20
+ gem.add_dependency 'sequel', '~> 3.42'
21
+ gem.add_dependency 'msgpack', '~> 0.5.1'
97
22
  end
98
-
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sequel::Plugins::Cacheable::DalliDriver do
4
+ let(:store) { DalliCli }
5
+
6
+ include_examples :driver
7
+ end
8
+
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sequel::Plugins::Cacheable::MemcacheDriver do
4
+ let(:store) { MemcacheCli }
5
+
6
+ include_examples :driver
7
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sequel::Plugins::Cacheable::RedisDriver do
4
+ let(:store) { RedisCli }
5
+
6
+ include_examples :driver
7
+ end
8
+
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sequel::Plugins::Cacheable::Driver do
4
+ let(:store) { RedisCli }
5
+
6
+ include_examples :driver
7
+
8
+ describe '.factory' do
9
+ subject { described_class.factory(store) }
10
+
11
+ context 'when Memcache' do
12
+ let(:store) { MemcacheCli }
13
+
14
+ it { should be_a(Sequel::Plugins::Cacheable::MemcacheDriver) }
15
+ end
16
+
17
+ context 'when Dalli' do
18
+ let(:store) { DalliCli }
19
+
20
+ it { should be_a(Sequel::Plugins::Cacheable::DalliDriver) }
21
+ end
22
+
23
+ context 'when Redis' do
24
+ let(:store) { RedisCli }
25
+
26
+ it { should be_a(Sequel::Plugins::Cacheable::RedisDriver) }
27
+ end
28
+
29
+ context 'when Unkown Store' do
30
+ let(:store) { mock }
31
+
32
+ it { should be_a(Sequel::Plugins::Cacheable::Driver) }
33
+ end
34
+ end
35
+ end
@@ -1,247 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- class RedisModel < Sequel::Model(:spec)
4
- end
5
-
6
- class MemcacheModel < Sequel::Model(:spec)
7
- plugin :cacheable, MemcacheCli
8
- end
9
-
10
- QueenCheck::Arbitrary(Float, Fixnum.arbitrary.gen)
11
- QueenCheck::Arbitrary(String, QueenCheck::Gen.quadratic(200).bind { | length |
12
- if length.zero?
13
- QueenCheck::Gen.unit("")
14
- else
15
- QueenCheck::Gen.rand.resize(1, length).fmap { | r |
16
- str = []
17
- r.times { str << QueenCheck::Alphabet.arbitrary.gen.value(0)[0] }
18
- str.join()
19
- }
20
- end
21
- })
22
-
23
3
  describe Sequel::Plugins::Cacheable do
24
- QueenCheck("Generate Test Datas",
25
- String, Fixnum, Float, Bignum, Boolean) do |string, fixnum, float, bignum, boolean|
26
- float = float * 1.0 / (10 ** (rand(4) + 1))
27
- RedisModel.create({
28
- :string => string,
29
- :integer => fixnum,
30
- :float => float,
31
- :bignum => bignum,
32
- :numeric => BigDecimal(float.to_s),
33
- :date => Date.today,
34
- :datetime => DateTime.now,
35
- :time => Time.now,
36
- :bool => boolean
37
- })
38
- true
39
- end
40
-
41
- context "NoNameClass" do
42
- before {
43
- @model = Class.new(Sequel::Model(:rspec))
44
- }
45
-
46
- it "should raise NoMethodError if the delete method is not found" do
47
- proc {
48
- @model.plugin :cacheable, 1
49
- }.should raise_error(NoMethodError)
50
- end
51
- end
52
-
53
- context MemcacheModel do
54
- subject { MemcacheModel }
55
-
56
- its("cache_store") { should == MemcacheCli }
57
- its("cache_store_type.set_with_ttl?") { should be_true }
58
- its("cache_store_type.delete_method") { should == :delete }
59
- its("cache_options.ttl") { should == 3600 }
60
- its("cache_options.ignore_exceptions") { should be_false }
61
- its("cache_options.pack_lib") { should == MessagePack }
62
-
63
- describe "cache control" do
64
- it "set" do
65
- MemcacheModel.cache_set('MemcacheModel::test', MemcacheModel[1])
66
- end
67
-
68
- it "get" do
69
- cache = MemcacheModel.cache_get('MemcacheModel::test')
70
- cache.should == MemcacheModel[1]
71
- end
72
-
73
- it "del" do
74
- MemcacheModel.cache_del('MemcacheModel::test')
75
- MemcacheModel.cache_get('MemcacheModel::test').should be_nil
76
- end
77
- end
78
-
79
- describe "act as cache" do
80
- context "Model[40]" do
81
- before do
82
- @obj = MemcacheModel[40]
83
- end
84
-
85
- it "stored cache" do
86
- MemcacheModel.cache_get(@obj.cache_key).should == @obj
87
- end
88
-
89
- it "restoreble cache data" do
90
- cached = MessagePack.unpack(MemcacheCli.get(@obj.cache_key))
91
- cached['string'].should == @obj.string
92
- Time.at(cached['time'][0], cached['time'][1]).should === @obj.time
93
- end
94
-
95
- it "update cache data" do
96
- @obj.string = 'modified++'
97
- cached = MessagePack.unpack(MemcacheCli.get(@obj.cache_key))
98
- cached['string'].should_not == @obj.string
99
- @obj.save
100
- cached = MessagePack.unpack(MemcacheCli.get(@obj.cache_key))
101
- cached['string'].should == @obj.string
102
- end
103
-
104
- it "delete cache data" do
105
- cache_key = @obj.cache_key; @obj.delete
106
- MemcacheCli.get(cache_key).should be_nil
107
- MemcacheModel[40].should be_nil
108
- end
109
-
110
- it "destroy cache data" do
111
- @obj = MemcacheModel[41]
112
- cache_key = @obj.cache_key; @obj.destroy
113
- MemcacheCli.get(cache_key).should be_nil
114
- MemcacheModel[41].should be_nil
115
- end
116
- end
117
- end
118
-
119
- describe "query cache" do
120
- it "get" do
121
- MemcacheModel.all.should == MemcacheModel.all
122
- end
123
-
124
- pending "not supported query cache on Memcache Client"
125
- end
126
- end
127
-
128
- context RedisModel do
129
- subject { RedisModel }
130
-
131
- it "should raise LoadError if the plugin is not found" do
132
- proc{ RedisModel.plugin :something_or_other}.should raise_error(LoadError)
133
- end
134
-
135
- its("columns") { should == [:id,:string,:integer,:float,:bignum,:numeric,:date,:datetime,:time,:bool] }
136
-
137
- its("plugins") {
138
- should_not include(Sequel::Plugins::Cacheable)
139
- RedisModel.plugin :cacheable, RedisCli
140
- should include(Sequel::Plugins::Cacheable)
141
- }
142
-
143
- its("cache_store") { should == RedisCli }
144
- its("cache_store_type.set_with_ttl?") { should be_false }
145
- its("cache_store_type.delete_method") { should == :del }
146
- its("cache_options.ttl") { should == 3600 }
147
- its("cache_options.ignore_exceptions") { should be_false }
148
- its("cache_options.pack_lib") { should == MessagePack }
149
-
150
- describe "cache control" do
151
- it "set" do
152
- RedisModel.cache_set('RedisModel::test', RedisModel[1])
153
- end
154
-
155
- it "get" do
156
- RedisModel.cache_get('RedisModel::test').should == RedisModel[1]
157
- end
158
-
159
- it "del" do
160
- RedisModel.cache_del('RedisModel::test')
161
- RedisModel.cache_get('RedisModel::test').should be_nil
162
- end
163
- end
164
-
165
- describe "act as cache" do
166
- context "Model[50]" do
167
- before do
168
- @obj = RedisModel[50]
169
- end
170
-
171
- it "unstored cache on new" do
172
- before_count = RedisCli.keys.length
173
- RedisModel.new({:string => 'test'})
174
- RedisCli.keys.length.should == before_count
175
- end
176
-
177
- it "stored cache" do
178
- RedisModel.cache_get(@obj.cache_key).should == @obj
179
- end
180
-
181
- it "restoreble cache data" do
182
- cached = MessagePack.unpack(RedisCli.get(@obj.cache_key))
183
- cached['string'].should == @obj.string
184
- Time.at(cached['time'][0], cached['time'][1]).should === @obj.time
185
- end
186
-
187
- it "update cache data" do
188
- @obj.string = 'modified++'
189
- cached = MessagePack.unpack(RedisCli.get(@obj.cache_key))
190
- cached['string'].should_not == @obj.string
191
- @obj.save
192
- cached = MessagePack.unpack(RedisCli.get(@obj.cache_key))
193
- cached['string'].should == @obj.string
194
- end
195
-
196
- it "delete cache data" do
197
- @obj.delete
198
- RedisCli.keys(@obj.cache_key).should == []
199
- RedisModel[50].should be_nil
200
- end
201
-
202
- it "destroy cache data" do
203
- @obj = RedisModel[51]
204
- @obj.delete
205
- RedisCli.keys(@obj.cache_key).should == []
206
- RedisModel[51].should be_nil
207
- end
208
- end
209
- end
210
-
211
- describe "query cache" do
212
- it "set and get" do
213
- RedisModel.clear_query_cache
214
- models = RedisModel.limit(3).all
215
- cache_key = RedisCli.keys('RedisModel::Query::*')[0]
216
- RedisModel.cache_get(cache_key).should == models
217
- end
218
-
219
- it "clear on update" do
220
- RedisModel.clear_query_cache
221
- RedisModel.all
222
- cache_key = RedisCli.keys('RedisModel::Query::*')
223
- cache_key.should_not be_empty
224
- RedisModel[2].save({:string => 'test++'})
225
- RedisCli.keys('RedisModel::Query::*').should be_empty
226
- end
227
-
228
- it "clear on delete" do
229
- RedisModel.clear_query_cache
230
- RedisModel.all
231
- cache_key = RedisCli.keys('RedisModel::Query::*')
232
- cache_key.should_not be_empty
233
- RedisModel[2].delete
234
- RedisCli.keys('RedisModel::Query::*').should be_empty
235
- end
236
-
237
- it "cacheout rescue" do
238
- RedisModel.clear_query_cache
239
- caches = RedisModel.limit(20).all
240
- cache_key = RedisCli.keys('RedisModel::Query::*')[0]
241
- cache = caches[rand(caches.length-1)]
242
- RedisModel.cache_del(cache.cache_key)
243
- RedisModel.cache_get(cache_key).should == caches
244
- end
245
- end
246
- end
4
+ it { should be_const_defined(:VERSION) }
247
5
  end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe DalliModel do
4
+ it_should_behave_like :cacheable
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe MemcacheModel do
4
+ it_should_behave_like :cacheable
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe RedisModel do
4
+ it_should_behave_like :cacheable
5
+ end