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.
- data/.gitignore +53 -0
- data/.pryrc +17 -0
- data/.rbenv-version +1 -0
- data/.travis.yml +4 -1
- data/Gemfile +21 -23
- data/Procfile +2 -0
- data/README.rdoc +4 -3
- data/Rakefile +1 -36
- data/lib/sequel-cacheable/class_methods.rb +74 -0
- data/lib/sequel-cacheable/dataset_methods.rb +53 -0
- data/lib/sequel-cacheable/driver/dalli.rb +19 -0
- data/lib/sequel-cacheable/driver/memcache.rb +15 -0
- data/lib/sequel-cacheable/driver/redis.rb +6 -0
- data/lib/sequel-cacheable/driver.rb +56 -0
- data/lib/sequel-cacheable/instance_methods.rb +66 -0
- data/lib/sequel-cacheable/packer.rb +34 -0
- data/lib/sequel-cacheable/version.rb +7 -0
- data/lib/sequel-cacheable.rb +18 -211
- data/sequel-cacheable.gemspec +18 -94
- data/spec/lib/sequel-cacheable/driver/dalli_driver_spec.rb +8 -0
- data/spec/lib/sequel-cacheable/driver/memcache_driver_spec.rb +7 -0
- data/spec/lib/sequel-cacheable/driver/redis_driver_spec.rb +8 -0
- data/spec/lib/sequel-cacheable/driver_spec.rb +35 -0
- data/spec/lib/sequel-cacheable_spec.rb +1 -243
- data/spec/models/dalli_spec.rb +5 -0
- data/spec/models/memcache_spec.rb +5 -0
- data/spec/models/redis_spec.rb +5 -0
- data/spec/shared/cacheable.rb +161 -0
- data/spec/shared/driver.rb +102 -0
- data/spec/spec_helper.rb +25 -28
- data/spec/support/models/dalli.rb +5 -0
- data/spec/support/models/memcache.rb +5 -0
- data/spec/support/models/redis.rb +5 -0
- metadata +57 -241
- data/Gemfile.lock +0 -66
- data/VERSION +0 -1
data/lib/sequel-cacheable.rb
CHANGED
@@ -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
|
-
@
|
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 =>
|
23
|
-
})
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
data/sequel-cacheable.gemspec
CHANGED
@@ -1,98 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
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 |
|
7
|
-
|
8
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
42
|
-
|
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,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
|
-
|
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
|