prosto_cache 0.1.3 → 0.2.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/Gemfile +3 -5
- data/Gemfile.lock +13 -15
- data/Rakefile +3 -0
- data/lib/prosto_cache.rb +129 -63
- data/prosto_cache.gemspec +10 -13
- data/spec/prosto_cache_spec.rb +86 -65
- data/spec/spec_helper.rb +1 -1
- metadata +9 -28
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,23 +1,21 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
diff-lcs (1.
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
rspec-
|
9
|
-
rspec-
|
10
|
-
|
11
|
-
rspec-
|
12
|
-
|
13
|
-
|
14
|
-
rspec-mocks (2.3.0)
|
4
|
+
diff-lcs (1.2.4)
|
5
|
+
rake (10.0.4)
|
6
|
+
rspec (2.13.0)
|
7
|
+
rspec-core (~> 2.13.0)
|
8
|
+
rspec-expectations (~> 2.13.0)
|
9
|
+
rspec-mocks (~> 2.13.0)
|
10
|
+
rspec-core (2.13.1)
|
11
|
+
rspec-expectations (2.13.0)
|
12
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
13
|
+
rspec-mocks (2.13.1)
|
15
14
|
|
16
15
|
PLATFORMS
|
17
16
|
ruby
|
18
17
|
|
19
18
|
DEPENDENCIES
|
20
|
-
bundler
|
21
|
-
|
22
|
-
|
23
|
-
rspec (~> 2.3.0)
|
19
|
+
bundler
|
20
|
+
rake
|
21
|
+
rspec
|
data/Rakefile
CHANGED
data/lib/prosto_cache.rb
CHANGED
@@ -1,63 +1,117 @@
|
|
1
1
|
=begin
|
2
2
|
This library provides a simple way to cache model and to access this cache in some canonical way.
|
3
3
|
Any changes to the model's objects will automatically result in cache reload.
|
4
|
-
Cache reload in other ruby processes of same app will be triggered as well, but
|
5
|
-
|
4
|
+
Cache reload in other ruby processes of same app will be triggered as well, but
|
5
|
+
with some delay (currently up to 60 seconds).
|
6
|
+
If delay in cache reloading is not an option, well, this simply library will
|
7
|
+
not work for you, and you have to use something fancier, like Memcached.
|
6
8
|
|
7
9
|
Usage:
|
8
|
-
|
10
|
+
|
11
|
+
* Add ProstoCache mixin to your model
|
9
12
|
class YourModel < ActiveRecord::Base
|
10
13
|
include ProstoCache
|
11
|
-
|
14
|
+
|
15
|
+
* Configure cache access keys (optional step, by default cache is accessed by key 'name')
|
12
16
|
cache_accessor_keys %w(scope name)
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
* Your model must have non-nullable column updated_at, add it in migration if
|
19
|
+
it is missing (this field is used for invalidating cache in other ruby processes).
|
20
|
+
|
21
|
+
* Access cached model object in your code like this
|
15
22
|
Simple case of one key
|
16
23
|
YourModel.cache[:key1]
|
17
|
-
Case of 2 or more keys
|
18
|
-
YourModel.cache[:key1
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
Case of 2 or more keys
|
25
|
+
YourModel.cache[:key1, :key2, :key3]
|
26
|
+
|
27
|
+
* Handling of non-existing cache values.
|
28
|
+
If cache is accessed using symbol key and value not found, it will raise BadCacheKeyError.
|
29
|
+
If cache is accessed using string key and value not found, it will return nil.
|
30
|
+
For complex keys type of last key component is the one taken into account.
|
31
|
+
|
32
|
+
* If you want to, you can add extra lookup helpers to the objects that relate
|
33
|
+
to the cached object, that will allow those objects to update 'string'
|
34
|
+
attribute, and that will result in database reference change.
|
22
35
|
class OtherModel < ActiveRecord::Base
|
23
36
|
belongs_to :your_model
|
24
37
|
lookup_enum_for :your_model
|
25
38
|
end
|
26
|
-
|
27
|
-
This lookup was intertionally not integrated with ActiveRecord since not everybody would want that, and monkey-patching other library (AR) is not really a good thing, even if it results in more magically 'smooth' experience.
|
28
|
-
Principle of least surprise, right?
|
29
|
-
=end
|
30
39
|
|
31
|
-
|
40
|
+
This lookup was intertionally not integrated 'seamlessly' with ActiveRecord since not
|
41
|
+
everybody would want that, and monkey-patching other library (AR) is not really
|
42
|
+
a good thing, even if it results in more 'smooth' experience where everything works as if by magic.
|
43
|
+
=end
|
32
44
|
|
33
45
|
module ProstoCache
|
46
|
+
class BadCacheKeyError < StandardError; end
|
47
|
+
class BadCacheValuesError < StandardError; end
|
48
|
+
|
34
49
|
# cache itself, contains pretty much all the logic
|
35
50
|
class ProstoModelCache
|
36
|
-
|
51
|
+
|
52
|
+
class ProstoHash
|
53
|
+
extend Forwardable
|
54
|
+
def initialize(hash = {})
|
55
|
+
@hash = hash.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
|
56
|
+
end
|
57
|
+
|
58
|
+
def [](key)
|
59
|
+
raise ArgumentError unless key
|
60
|
+
hash[key.to_sym]
|
61
|
+
end
|
62
|
+
|
63
|
+
def []=(key, value)
|
64
|
+
raise ArgumentError unless key
|
65
|
+
hash[key.to_sym] = value
|
66
|
+
end
|
67
|
+
|
68
|
+
def_delegators :hash, :to_s, :inspect
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
attr_reader :hash
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.fail_on_missing_value?(litmus)
|
76
|
+
case litmus
|
77
|
+
when Symbol
|
78
|
+
true
|
79
|
+
when String
|
80
|
+
false
|
81
|
+
else
|
82
|
+
raise ArgumentError, "Unknown type of cache key #{litmus.inspect}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
MAX_CACHE_LIFE = 60 # seconds
|
37
87
|
|
38
88
|
def initialize(model_class, accessor_keys)
|
39
|
-
|
40
|
-
|
89
|
+
raise ArgumentError, "No model class provided" unless model_class
|
90
|
+
|
91
|
+
@model_class = model_class
|
92
|
+
@accessor_keys = [*(accessor_keys || :name)]
|
41
93
|
end
|
42
94
|
|
43
95
|
def invalidate
|
44
96
|
self.cache = self.signature = self.validated_at = nil
|
45
97
|
end
|
46
98
|
|
47
|
-
def [](keys)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
99
|
+
def [](*keys)
|
100
|
+
unless keys.length == accessor_keys.length
|
101
|
+
raise BadCacheKeyError, "Cached accessed by #{keys.length} keys, expected #{accessor_keys.length}"
|
102
|
+
end
|
103
|
+
|
104
|
+
keys.zip((1..keys.length)).inject(safe_cache) do |memo, (key, index)|
|
105
|
+
value = memo[key]
|
106
|
+
unless value
|
107
|
+
if ProstoModelCache.fail_on_missing_value?(keys.last)
|
108
|
+
raise BadCacheKeyError, key
|
109
|
+
else
|
110
|
+
value = ProstoHash.new unless index == keys.length
|
57
111
|
end
|
58
112
|
end
|
59
|
-
|
60
|
-
|
113
|
+
|
114
|
+
value
|
61
115
|
end
|
62
116
|
end
|
63
117
|
|
@@ -71,56 +125,71 @@ module ProstoCache
|
|
71
125
|
|
72
126
|
private
|
73
127
|
|
128
|
+
attr_reader :model_class, :cache, :signature, :validated_at, :accessor_keys
|
129
|
+
attr_writer :cache, :signature, :validated_at
|
130
|
+
|
74
131
|
def safe_cache
|
75
|
-
|
76
|
-
|
132
|
+
time = Time.now.to_i
|
133
|
+
|
134
|
+
if cache && validated_at < time - MAX_CACHE_LIFE
|
135
|
+
current_cache_signature = validate_cache_signature(time)
|
136
|
+
end
|
137
|
+
|
138
|
+
unless cache
|
139
|
+
load_cache(time, current_cache_signature)
|
140
|
+
end
|
77
141
|
|
78
|
-
|
79
|
-
|
142
|
+
cache
|
143
|
+
end
|
144
|
+
|
145
|
+
def validate_cache_signature(time)
|
146
|
+
query_cache_signature.tap { |current_cache_signature|
|
80
147
|
if current_cache_signature == signature
|
81
|
-
self.validated_at =
|
148
|
+
self.validated_at = time
|
82
149
|
else
|
83
150
|
invalidate
|
84
151
|
end
|
85
|
-
|
152
|
+
}
|
153
|
+
end
|
86
154
|
|
87
|
-
|
88
|
-
|
155
|
+
def load_cache(time, current_cache_signature = nil)
|
156
|
+
fail "Can not load already loaded cache" if cache
|
89
157
|
|
90
|
-
|
91
|
-
self.validated_at = current_time
|
92
|
-
self.signature = current_cache_signature
|
93
|
-
end
|
158
|
+
current_cache_signature ||= query_cache_signature
|
94
159
|
|
95
|
-
|
160
|
+
self.cache = build_cache(model_class.all, accessor_keys)
|
161
|
+
self.validated_at = time
|
162
|
+
self.signature = current_cache_signature
|
96
163
|
end
|
97
164
|
|
98
|
-
|
99
|
-
|
100
|
-
|
165
|
+
|
166
|
+
def build_cache(objects, attributes=[])
|
167
|
+
attributes = [*attributes]
|
168
|
+
if attributes.empty?
|
101
169
|
# terminal case
|
102
|
-
raise "No cache entry found" if objects.nil? || objects.empty?
|
103
|
-
raise "Non deterministic search result, more then one cache entry found" if objects.size > 1
|
170
|
+
raise BadCacheValuesError, "No cache entry found" if objects.nil? || objects.empty?
|
171
|
+
raise BadCacheValuesError, "Non deterministic search result, more then one cache entry found" if objects.size > 1
|
104
172
|
return objects.first
|
105
173
|
else
|
106
174
|
reduced_attributes = attributes.dup
|
107
175
|
attribute = reduced_attributes.delete_at(0).to_sym
|
108
|
-
|
176
|
+
# first, bucketize to reduce problem's complexity
|
177
|
+
array_map = objects.each_with_object({}) do |o, memo|
|
109
178
|
key = o.send(attribute).to_s
|
110
179
|
memo[key] ||= []
|
111
180
|
memo[key] << o
|
112
|
-
memo
|
113
181
|
end
|
114
|
-
|
115
|
-
|
116
|
-
memo[
|
117
|
-
memo
|
182
|
+
# second, recurse and build cache from those reduced buckets!
|
183
|
+
array_map.each_with_object(ProstoHash.new) do |(attr_value, attr_bucket), memo|
|
184
|
+
memo[attr_value] = build_cache(attr_bucket, reduced_attributes)
|
118
185
|
end
|
119
186
|
end
|
120
187
|
end
|
121
188
|
|
122
189
|
def query_cache_signature
|
123
|
-
raw_result = ActiveRecord::Base.connection.execute
|
190
|
+
raw_result = ActiveRecord::Base.connection.execute(
|
191
|
+
"select max(updated_at) as max_updated_at, max(id) as max_id, count(id) as count from #{model_class.table_name}"
|
192
|
+
)
|
124
193
|
array_result = case raw_result.class.name
|
125
194
|
when 'Mysql::Result'
|
126
195
|
[].tap { |rows| raw_result.each_hash { |h| rows << h } }
|
@@ -129,7 +198,7 @@ module ProstoCache
|
|
129
198
|
when 'PGresult'
|
130
199
|
raw_result.map(&:to_hash)
|
131
200
|
else
|
132
|
-
|
201
|
+
fail "Result class #{raw_result.class.name} in unsupported"
|
133
202
|
end
|
134
203
|
array_result.map(&:symbolize_keys).first
|
135
204
|
end
|
@@ -150,9 +219,10 @@ module ProstoCache
|
|
150
219
|
end
|
151
220
|
end
|
152
221
|
end
|
153
|
-
|
222
|
+
|
223
|
+
module Extensions
|
154
224
|
def lookup_enum_for(name, enum_class=nil)
|
155
|
-
raise unless name
|
225
|
+
raise ArgumentError, "No name provided" unless name
|
156
226
|
enum_class = name.to_s.classify.constantize unless enum_class
|
157
227
|
define_method("#{name}_with_lookup=") do |o|
|
158
228
|
new_value = o
|
@@ -166,7 +236,3 @@ module ProstoCache
|
|
166
236
|
end
|
167
237
|
end
|
168
238
|
end
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
data/prosto_cache.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "prosto_cache"
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Olek Poplavsky"]
|
@@ -35,20 +35,17 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.specification_version = 3
|
36
36
|
|
37
37
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
38
|
-
s.
|
39
|
-
s.add_development_dependency(%q<
|
40
|
-
s.add_development_dependency(%q<
|
41
|
-
s.add_development_dependency(%q<rake>, ["= 0.8.7"])
|
38
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3"])
|
39
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.1"])
|
40
|
+
s.add_development_dependency(%q<rake>)
|
42
41
|
else
|
43
|
-
s.add_dependency(%q<
|
44
|
-
s.add_dependency(%q<
|
45
|
-
s.add_dependency(%q<
|
46
|
-
s.add_dependency(%q<rake>, ["= 0.8.7"])
|
42
|
+
s.add_dependency(%q<rspec>, ["~> 2.3"])
|
43
|
+
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
44
|
+
s.add_dependency(%q<rake>)
|
47
45
|
end
|
48
46
|
else
|
49
|
-
s.add_dependency(%q<
|
50
|
-
s.add_dependency(%q<
|
51
|
-
s.add_dependency(%q<
|
52
|
-
s.add_dependency(%q<rake>, ["= 0.8.7"])
|
47
|
+
s.add_dependency(%q<rspec>, ["~> 2.3"])
|
48
|
+
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
49
|
+
s.add_dependency(%q<rake>)
|
53
50
|
end
|
54
51
|
end
|
data/spec/prosto_cache_spec.rb
CHANGED
@@ -5,69 +5,80 @@ describe "ProstoCache" do
|
|
5
5
|
Object.send(:remove_const, 'Foo') if Object.const_defined? 'Foo'
|
6
6
|
|
7
7
|
class Foo; end
|
8
|
-
Foo.
|
9
|
-
class Foo
|
10
|
-
include ProstoCache
|
11
|
-
end
|
8
|
+
Foo.stub(:after_save)
|
12
9
|
end
|
13
10
|
|
14
|
-
|
15
|
-
|
11
|
+
describe '#cache' do
|
12
|
+
before do
|
13
|
+
class Foo
|
14
|
+
include ProstoCache
|
15
|
+
end
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
it "should add a cache method" do
|
19
|
+
Foo.cache.should_not be_nil
|
20
|
+
Foo.cache.should be_an_instance_of(ProstoCache::ProstoModelCache)
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
it "should not load cache if it was never accessed" do
|
24
|
+
Foo.cache.should_not_receive(:query_cache_signature)
|
25
|
+
Foo.should_not_receive(:all)
|
26
|
+
|
27
|
+
Foo.cache.should_not be_nil
|
28
|
+
end
|
26
29
|
end
|
27
30
|
|
28
31
|
context "[] method with single key access" do
|
29
32
|
before do
|
30
|
-
Object.send(:remove_const, 'Foo') if Object.const_defined? 'Foo'
|
31
|
-
|
32
33
|
class Foo
|
34
|
+
include ProstoCache
|
35
|
+
|
33
36
|
attr_accessor :name
|
34
37
|
def initialize(name)
|
35
38
|
self.name = name
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
39
|
-
Foo.
|
40
|
-
|
41
|
-
class Foo
|
42
|
-
include ProstoCache
|
43
|
-
end
|
44
|
-
|
45
|
-
Foo.cache.should_not be_nil
|
46
|
-
Foo.cache.should_receive(:query_cache_signature).once.and_return(:foo)
|
47
|
-
Foo.should_receive(:all).once.and_return(%w(foo bar).map { |n| Foo.new(n) })
|
42
|
+
Foo.cache.stub(:query_cache_signature).once.and_return(:foo)
|
43
|
+
Foo.stub(:all).once.and_return(%w(foo bar).map { |n| Foo.new(n) })
|
48
44
|
end
|
49
45
|
|
50
46
|
it "should load cache when it is accessed" do
|
51
|
-
Foo.
|
47
|
+
Foo.should_receive(:all).once.and_return(%w(foo bar).map { |n| Foo.new(n) })
|
48
|
+
|
49
|
+
Foo.cache[:foo]
|
52
50
|
end
|
53
51
|
|
54
|
-
|
55
|
-
|
52
|
+
context 'when key is symbol' do
|
53
|
+
it "should raise an error for key that was not found" do
|
54
|
+
expect { Foo.cache[:nondef] }.to raise_error ProstoCache::BadCacheKeyError
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return proper object for key that was found" do
|
58
|
+
Foo.cache[:foo].should_not be_nil
|
59
|
+
Foo.cache[:foo].name.should == 'foo'
|
60
|
+
end
|
56
61
|
end
|
57
62
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
63
|
+
context 'when key is string' do
|
64
|
+
it "should return nil for key that was not found" do
|
65
|
+
Foo.cache['nondef'].should be_nil
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should return proper object for key that was found" do
|
69
|
+
Foo.cache['foo'].should_not be_nil
|
70
|
+
Foo.cache['foo'].name.should == 'foo'
|
71
|
+
end
|
62
72
|
end
|
63
73
|
end
|
64
74
|
|
65
75
|
context "[] method with composite key access" do
|
66
76
|
before do
|
67
|
-
Object.send(:remove_const, 'Foo') if Object.const_defined? 'Foo'
|
68
|
-
|
69
77
|
class Foo
|
70
|
-
|
78
|
+
include ProstoCache
|
79
|
+
cache_accessor_keys %w(key1 key2)
|
80
|
+
|
81
|
+
attr_accessor :name, :key1, :key2
|
71
82
|
def initialize(name, key1, key2)
|
72
83
|
self.name = name
|
73
84
|
self.key1 = key1
|
@@ -75,46 +86,56 @@ describe "ProstoCache" do
|
|
75
86
|
end
|
76
87
|
end
|
77
88
|
|
78
|
-
Foo.
|
79
|
-
|
80
|
-
class Foo
|
81
|
-
include ProstoCache
|
82
|
-
cache_accessor_keys %w(key1 key2)
|
83
|
-
end
|
84
|
-
|
85
|
-
Foo.cache.should_not be_nil
|
86
|
-
Foo.cache.should_receive(:query_cache_signature).once.and_return(:foo)
|
87
|
-
Foo.should_receive(:all).once.and_return(%w(foo bar).map { |n| Foo.new(n, n + '1', n + '2') })
|
89
|
+
Foo.cache.stub(:query_cache_signature).once.and_return(:foo)
|
90
|
+
Foo.stub(:all).once.and_return(%w(foo bar).map { |n| Foo.new(n, n + '1', n + '2') })
|
88
91
|
end
|
89
92
|
|
90
|
-
it "should
|
91
|
-
Foo.cache[:nondef].
|
93
|
+
it "should raise an error when not enough keys provided" do
|
94
|
+
expect { Foo.cache[:nondef] }.to raise_error ProstoCache::BadCacheKeyError
|
95
|
+
expect { Foo.cache[:foo1] }.to raise_error ProstoCache::BadCacheKeyError
|
96
|
+
expect { Foo.cache['nondef'] }.to raise_error ProstoCache::BadCacheKeyError
|
97
|
+
expect { Foo.cache['foo1'] }.to raise_error ProstoCache::BadCacheKeyError
|
92
98
|
end
|
93
99
|
|
94
|
-
it "should
|
95
|
-
Foo.cache[:
|
100
|
+
it "should raise an error when too many keys provided" do
|
101
|
+
expect { Foo.cache[:nondef1, :nondef2, :nondef3] }.to raise_error ProstoCache::BadCacheKeyError
|
102
|
+
expect { Foo.cache[:foo1, :foo2, :nondef] }.to raise_error ProstoCache::BadCacheKeyError
|
103
|
+
expect { Foo.cache['nondef1', 'nondef2', 'nondef3'] }.to raise_error ProstoCache::BadCacheKeyError
|
104
|
+
expect { Foo.cache['foo1', 'foo2', 'nondef'] }.to raise_error ProstoCache::BadCacheKeyError
|
96
105
|
end
|
97
106
|
|
98
|
-
|
99
|
-
|
100
|
-
|
107
|
+
context 'when last key is symbol' do
|
108
|
+
it "should raise an error for first key that was not found" do
|
109
|
+
expect { Foo.cache[:undef, :foo2] }.to raise_error ProstoCache::BadCacheKeyError
|
110
|
+
expect { Foo.cache['undef', :foo2] }.to raise_error ProstoCache::BadCacheKeyError
|
111
|
+
end
|
101
112
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
113
|
+
it "should raise an error for last key that was not found" do
|
114
|
+
expect { Foo.cache[:foo1, :nondef] }.to raise_error ProstoCache::BadCacheKeyError
|
115
|
+
expect { Foo.cache['foo1', :nondef] }.to raise_error ProstoCache::BadCacheKeyError
|
116
|
+
end
|
107
117
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
118
|
+
it "should return proper object for key that was found" do
|
119
|
+
Foo.cache[:foo1, :foo2].should_not be_nil
|
120
|
+
Foo.cache[:foo1, :foo2].name.should == 'foo'
|
121
|
+
end
|
112
122
|
end
|
113
123
|
|
114
|
-
|
115
|
-
|
116
|
-
Foo.cache[
|
117
|
-
|
124
|
+
context 'when last key is string' do
|
125
|
+
it "should return nil for first level key that was not found" do
|
126
|
+
Foo.cache['nondef', 'foo2'].should be_nil
|
127
|
+
Foo.cache[:nondef, 'foo2'].should be_nil
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should return nil for second level key that was not found" do
|
131
|
+
Foo.cache['foo1', 'nondef'].should be_nil
|
132
|
+
Foo.cache[:foo1, 'nondef'].should be_nil
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should return proper object for key that was found" do
|
136
|
+
Foo.cache['foo1', 'foo2'].should_not be_nil
|
137
|
+
Foo.cache['foo1', 'foo2'].name.should == 'foo'
|
138
|
+
end
|
118
139
|
end
|
119
140
|
end
|
120
141
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
2
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
3
4
|
require 'rspec'
|
4
5
|
require 'prosto_cache'
|
5
6
|
|
@@ -8,5 +9,4 @@ require 'prosto_cache'
|
|
8
9
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
10
|
|
10
11
|
RSpec.configure do |config|
|
11
|
-
|
12
12
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prosto_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,22 +11,6 @@ bindir: bin
|
|
11
11
|
cert_chain: []
|
12
12
|
date: 2011-05-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: hashie
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 1.0.0
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 1.0.0
|
30
14
|
- !ruby/object:Gem::Dependency
|
31
15
|
name: rspec
|
32
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -34,7 +18,7 @@ dependencies:
|
|
34
18
|
requirements:
|
35
19
|
- - ~>
|
36
20
|
- !ruby/object:Gem::Version
|
37
|
-
version: 2.3
|
21
|
+
version: '2.3'
|
38
22
|
type: :development
|
39
23
|
prerelease: false
|
40
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +26,7 @@ dependencies:
|
|
42
26
|
requirements:
|
43
27
|
- - ~>
|
44
28
|
- !ruby/object:Gem::Version
|
45
|
-
version: 2.3
|
29
|
+
version: '2.3'
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
31
|
name: bundler
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +34,7 @@ dependencies:
|
|
50
34
|
requirements:
|
51
35
|
- - ~>
|
52
36
|
- !ruby/object:Gem::Version
|
53
|
-
version: 1.1
|
37
|
+
version: '1.1'
|
54
38
|
type: :development
|
55
39
|
prerelease: false
|
56
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,23 +42,23 @@ dependencies:
|
|
58
42
|
requirements:
|
59
43
|
- - ~>
|
60
44
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.1
|
45
|
+
version: '1.1'
|
62
46
|
- !ruby/object:Gem::Dependency
|
63
47
|
name: rake
|
64
48
|
requirement: !ruby/object:Gem::Requirement
|
65
49
|
none: false
|
66
50
|
requirements:
|
67
|
-
- - '
|
51
|
+
- - ! '>='
|
68
52
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0
|
53
|
+
version: '0'
|
70
54
|
type: :development
|
71
55
|
prerelease: false
|
72
56
|
version_requirements: !ruby/object:Gem::Requirement
|
73
57
|
none: false
|
74
58
|
requirements:
|
75
|
-
- - '
|
59
|
+
- - ! '>='
|
76
60
|
- !ruby/object:Gem::Version
|
77
|
-
version: 0
|
61
|
+
version: '0'
|
78
62
|
description: Use this gem if you want a simple 'enum-like' cache for your models that
|
79
63
|
does not restrict updates, but will stay current with them.
|
80
64
|
email: olek@woodenbits.com
|
@@ -107,9 +91,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
91
|
- - ! '>='
|
108
92
|
- !ruby/object:Gem::Version
|
109
93
|
version: '0'
|
110
|
-
segments:
|
111
|
-
- 0
|
112
|
-
hash: 849790085734229441
|
113
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
95
|
none: false
|
115
96
|
requirements:
|