prosto_cache 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --color
2
+ --format
3
+ documentation
4
+ --backtrace
5
+
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "yard", "~> 0.6.0"
11
+ gem "bundler", "~> 1.0.0"
12
+ gem "jeweler", "~> 1.6.0"
13
+ gem "rcov", ">= 0"
14
+ gem "reek", "~> 1.2.8"
15
+ gem "roodi", "~> 2.1.0"
16
+ gem "rake", "0.8.7"
17
+ end
18
+
19
+ gem "hashie", ">= 1.0.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,47 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ hashie (1.0.0)
7
+ jeweler (1.6.0)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rake (0.8.7)
12
+ rcov (0.9.9)
13
+ reek (1.2.8)
14
+ ruby2ruby (~> 1.2)
15
+ ruby_parser (~> 2.0)
16
+ sexp_processor (~> 3.0)
17
+ roodi (2.1.0)
18
+ ruby_parser
19
+ rspec (2.3.0)
20
+ rspec-core (~> 2.3.0)
21
+ rspec-expectations (~> 2.3.0)
22
+ rspec-mocks (~> 2.3.0)
23
+ rspec-core (2.3.1)
24
+ rspec-expectations (2.3.0)
25
+ diff-lcs (~> 1.1.2)
26
+ rspec-mocks (2.3.0)
27
+ ruby2ruby (1.2.5)
28
+ ruby_parser (~> 2.0)
29
+ sexp_processor (~> 3.0)
30
+ ruby_parser (2.0.6)
31
+ sexp_processor (~> 3.0)
32
+ sexp_processor (3.0.5)
33
+ yard (0.6.8)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ bundler (~> 1.0.0)
40
+ hashie (>= 1.0.0)
41
+ jeweler (~> 1.6.0)
42
+ rake (= 0.8.7)
43
+ rcov
44
+ reek (~> 1.2.8)
45
+ roodi (~> 2.1.0)
46
+ rspec (~> 2.3.0)
47
+ yard (~> 0.6.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Olek Poplavsky
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = prosto_cache
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to prosto_cache
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Olek Poplavsky. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "prosto_cache"
18
+ gem.homepage = "http://github.com/olek/prosto_cache"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Very simple caching for your ActiveRecord models.}
21
+ gem.description = %Q{Use this gem if you want a simple 'enum-like' cache for your models that does not restrict updates, but will stay current with them.}
22
+ gem.email = "olek@woodenbits.com"
23
+ gem.authors = ["Olek Poplavsky"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ require 'reek/rake/task'
40
+ Reek::Rake::Task.new do |t|
41
+ t.fail_on_error = true
42
+ t.verbose = false
43
+ t.source_files = 'lib/**/*.rb'
44
+ end
45
+
46
+ require 'roodi'
47
+ require 'roodi_task'
48
+ RoodiTask.new do |t|
49
+ t.verbose = false
50
+ end
51
+
52
+ task :default => :spec
53
+
54
+ require 'yard'
55
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,139 @@
1
+ =begin
2
+ This library provides a simple way to cache model and to access this cache in some canonical way.
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 with some delay (currently up to 60 seconds).
5
+ If delay in cache reloading is not an option, well, this simply library will not work for you, and you have to use something fancier, like Memcached.
6
+
7
+ Usage:
8
+ 1. add ProstoCache mixin to your model
9
+ class YourModel < ActiveRecord::Base
10
+ include ProstoCache
11
+ 2. Configure cache access keys (optional step, by default cache is accessed by key 'name')
12
+ cache_accessor_keys %w(scope name)
13
+ 3. Your model must have non-nullable column updated_at, add it in migration if it is missing (this field is used for invalidating cache in other ruby processes).
14
+ 4. Access cached model object in your code like this
15
+ Simple case of one key
16
+ YourModel.cache[:key1]
17
+ Case of 2 or more keys where it is known ahead of time that all parent keys exist. Looks conventional, but is unreliable because brackets operation on nill will raise an error.
18
+ YourModel.cache[:key1][:key2][:key3]
19
+ Case of 2 or more keys where any key may not be present in cache, and expected answer is nil. Looks so-so, but is much more reliable then previos use case.
20
+ YourModel.cache[[:key1, :key2, :key3]]
21
+ =end
22
+
23
+ require 'hashie'
24
+
25
+ module ProstoCache
26
+ # cache itself, contains pretty much all the logic
27
+ class ProstoModelCache
28
+ attr_accessor :model_class, :cache, :signature, :validated_at, :accessor_keys
29
+
30
+ def initialize(model_class, accessor_keys)
31
+ self.model_class = model_class
32
+ self.accessor_keys = accessor_keys || 'name'
33
+ end
34
+
35
+ def invalidate
36
+ self.cache = self.signature = self.validated_at = nil
37
+ end
38
+
39
+ def [](keys)
40
+ if keys.respond_to?(:to_ary)
41
+ keys_ary = keys.to_ary
42
+ if keys_ary.empty?
43
+ nil
44
+ else
45
+ # looks like an array of key was passed in, lets try them one after another, without failing
46
+ keys_ary.inject(safe_cache) do |memo,key|
47
+ break unless memo
48
+ memo[key]
49
+ end
50
+ end
51
+ else
52
+ safe_cache[keys]
53
+ end
54
+ end
55
+
56
+ def keys
57
+ safe_cache.keys
58
+ end
59
+
60
+ def values
61
+ safe_cache.values
62
+ end
63
+
64
+ private
65
+
66
+ def safe_cache
67
+ max_cache_life = 60 # seconds
68
+ current_time = Time.now.to_i
69
+
70
+ if cache && validated_at < current_time - max_cache_life
71
+ current_cache_signature = query_cache_signature
72
+ if current_cache_signature == signature
73
+ self.validated_at = current_time
74
+ else
75
+ invalidate
76
+ end
77
+ end
78
+
79
+ unless cache
80
+ current_cache_signature ||= query_cache_signature
81
+
82
+ self.cache = build_cache(model_class.all, accessor_keys)
83
+ self.validated_at = current_time
84
+ self.signature = current_cache_signature
85
+ end
86
+
87
+ return cache
88
+ end
89
+
90
+ def build_cache(objects, attributes=nil)
91
+ attributes = [*attributes] if attributes
92
+ if !attributes || attributes.empty?
93
+ # terminal case
94
+ raise "No cache entry found" if objects.nil? || objects.empty?
95
+ raise "Non deterministic search result, more then one cache entry found" if objects.size > 1
96
+ return objects.first
97
+ else
98
+ reduced_attributes = attributes.dup
99
+ attribute = reduced_attributes.delete_at(0).to_sym
100
+ array_map = objects.inject({}) do |memo, o|
101
+ key = o.send(attribute).to_s
102
+ memo[key] ||= []
103
+ memo[key] << o
104
+ memo
105
+ end
106
+ array_map.inject(Hashie::Mash.new) do |memo, (k, v)|
107
+ # recursion !
108
+ memo[k] = build_cache(v, reduced_attributes)
109
+ memo
110
+ end
111
+ end
112
+ end
113
+
114
+ def query_cache_signature
115
+ raw_result = ActiveRecord::Base.connection.execute "select max(updated_at) as max_updated_at, max(id) as max_id, count(id) as count from #{model_class.name.tableize}"
116
+ raw_result.map(&:to_hash).map(&:symbolize_keys).first
117
+ end
118
+ end
119
+
120
+ def self.included(cl)
121
+
122
+ cl.after_save { cl.cache.invalidate }
123
+
124
+ class << cl
125
+
126
+ def cache
127
+ @cache ||= ProstoModelCache.new self, @accessor_keys
128
+ end
129
+
130
+ def cache_accessor_keys(keys)
131
+ @accessor_keys = keys
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+
138
+
139
+
@@ -0,0 +1,120 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "ProstoCache" do
4
+ before do
5
+ Object.send(:remove_const, 'Foo') if Object.const_defined? 'Foo'
6
+
7
+ class Foo; end
8
+ Foo.should_receive(:after_save)
9
+ class Foo
10
+ include ProstoCache
11
+ end
12
+ end
13
+
14
+ it "should be a mix-in" do
15
+ end
16
+
17
+ it "should add a cache method" do
18
+ Foo.cache.should_not be_nil
19
+ Foo.cache.should be_an_instance_of(ProstoCache::ProstoModelCache)
20
+ end
21
+
22
+ it "should not load cache if it was never accessed" do
23
+ Foo.cache.should_not be_nil
24
+ Foo.cache.should_not_receive(:query_cache_signature)
25
+ Foo.should_not_receive(:all)
26
+ end
27
+
28
+ context "[] method with single key access" do
29
+ before do
30
+ Object.send(:remove_const, 'Foo') if Object.const_defined? 'Foo'
31
+
32
+ class Foo
33
+ attr_accessor :name
34
+ def initialize(name)
35
+ self.name = name
36
+ end
37
+ end
38
+
39
+ Foo.should_receive(:after_save)
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) })
48
+ end
49
+
50
+ it "should load cache when it is accessed" do
51
+ Foo.cache[:nondef]
52
+ end
53
+
54
+ it "should return nil for key that was not found" do
55
+ Foo.cache[:nondef].should be_nil
56
+ end
57
+
58
+ it "should return proper object for key that was found" do
59
+ Foo.cache[:foo].should_not be_nil
60
+ Foo.cache[:foo].name.should == 'foo'
61
+ Foo.cache[:bar].name.should == 'bar'
62
+ end
63
+ end
64
+
65
+ context "[] method with composite key access" do
66
+ before do
67
+ Object.send(:remove_const, 'Foo') if Object.const_defined? 'Foo'
68
+
69
+ class Foo
70
+ attr_accessor :key1, :key2, :name
71
+ def initialize(name, key1, key2)
72
+ self.name = name
73
+ self.key1 = key1
74
+ self.key2 = key2
75
+ end
76
+ end
77
+
78
+ Foo.should_receive(:after_save)
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') })
88
+ end
89
+
90
+ it "should return nil for first level key that was not found" do
91
+ Foo.cache[:nondef].should be_nil
92
+ end
93
+
94
+ it "should return nil for second level key that was not found" do
95
+ Foo.cache[:foo1][:nondef].should be_nil
96
+ end
97
+
98
+ it "should return nil for safe access method when first level key was not found" do
99
+ Foo.cache[[:nodef, :foo2]].should be_nil
100
+ end
101
+
102
+ it "should return proper object for key that was found, using unsafe access method" do
103
+ Foo.cache[:foo1][:foo2].should_not be_nil
104
+ Foo.cache[:foo1][:foo2].name.should == 'foo'
105
+ Foo.cache[:bar1][:bar2].name.should == 'bar'
106
+ end
107
+
108
+ it "should return proper object for key that was found, using safe access method" do
109
+ Foo.cache[[:foo1, :foo2]].should_not be_nil
110
+ Foo.cache[[:foo1, :foo2]].name.should == 'foo'
111
+ Foo.cache[[:bar1, :bar2]].name.should == 'bar'
112
+ end
113
+
114
+ it "should fail with exception for the unsafe access method when first level key that was not found" do
115
+ lambda {
116
+ Foo.cache[:nondef][:foo2]
117
+ }.should raise_error
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'prosto_cache'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,235 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prosto_cache
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Olek Poplavsky
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-25 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ type: :runtime
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ name: hashie
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ prerelease: false
39
+ type: :development
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 2
48
+ - 3
49
+ - 0
50
+ version: 2.3.0
51
+ name: rspec
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ prerelease: false
55
+ type: :development
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 7
62
+ segments:
63
+ - 0
64
+ - 6
65
+ - 0
66
+ version: 0.6.0
67
+ name: yard
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ prerelease: false
71
+ type: :development
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ hash: 23
78
+ segments:
79
+ - 1
80
+ - 0
81
+ - 0
82
+ version: 1.0.0
83
+ name: bundler
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ prerelease: false
87
+ type: :development
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ hash: 15
94
+ segments:
95
+ - 1
96
+ - 6
97
+ - 0
98
+ version: 1.6.0
99
+ name: jeweler
100
+ version_requirements: *id005
101
+ - !ruby/object:Gem::Dependency
102
+ prerelease: false
103
+ type: :development
104
+ requirement: &id006 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 3
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ name: rcov
114
+ version_requirements: *id006
115
+ - !ruby/object:Gem::Dependency
116
+ prerelease: false
117
+ type: :development
118
+ requirement: &id007 !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ~>
122
+ - !ruby/object:Gem::Version
123
+ hash: 15
124
+ segments:
125
+ - 1
126
+ - 2
127
+ - 8
128
+ version: 1.2.8
129
+ name: reek
130
+ version_requirements: *id007
131
+ - !ruby/object:Gem::Dependency
132
+ prerelease: false
133
+ type: :development
134
+ requirement: &id008 !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ~>
138
+ - !ruby/object:Gem::Version
139
+ hash: 11
140
+ segments:
141
+ - 2
142
+ - 1
143
+ - 0
144
+ version: 2.1.0
145
+ name: roodi
146
+ version_requirements: *id008
147
+ - !ruby/object:Gem::Dependency
148
+ prerelease: false
149
+ type: :development
150
+ requirement: &id009 !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - "="
154
+ - !ruby/object:Gem::Version
155
+ hash: 49
156
+ segments:
157
+ - 0
158
+ - 8
159
+ - 7
160
+ version: 0.8.7
161
+ name: rake
162
+ version_requirements: *id009
163
+ description: Use this gem if you want a simple 'enum-like' cache for your models that does not restrict updates, but will stay current with them.
164
+ email: olek@woodenbits.com
165
+ executables: []
166
+
167
+ extensions: []
168
+
169
+ extra_rdoc_files:
170
+ - LICENSE.txt
171
+ - README.rdoc
172
+ files:
173
+ - .document
174
+ - .rspec
175
+ - Gemfile
176
+ - Gemfile.lock
177
+ - LICENSE.txt
178
+ - README.rdoc
179
+ - Rakefile
180
+ - VERSION
181
+ - lib/prosto_cache.rb
182
+ - spec/prosto_cache_spec.rb
183
+ - spec/spec_helper.rb
184
+ - vendor/cache/diff-lcs-1.1.2.gem
185
+ - vendor/cache/git-1.2.5.gem
186
+ - vendor/cache/hashie-1.0.0.gem
187
+ - vendor/cache/jeweler-1.6.0.gem
188
+ - vendor/cache/rake-0.8.7.gem
189
+ - vendor/cache/rcov-0.9.9.gem
190
+ - vendor/cache/reek-1.2.8.gem
191
+ - vendor/cache/roodi-2.1.0.gem
192
+ - vendor/cache/rspec-2.3.0.gem
193
+ - vendor/cache/rspec-core-2.3.1.gem
194
+ - vendor/cache/rspec-expectations-2.3.0.gem
195
+ - vendor/cache/rspec-mocks-2.3.0.gem
196
+ - vendor/cache/ruby2ruby-1.2.5.gem
197
+ - vendor/cache/ruby_parser-2.0.6.gem
198
+ - vendor/cache/sexp_processor-3.0.5.gem
199
+ - vendor/cache/yard-0.6.8.gem
200
+ has_rdoc: true
201
+ homepage: http://github.com/olek/prosto_cache
202
+ licenses:
203
+ - MIT
204
+ post_install_message:
205
+ rdoc_options: []
206
+
207
+ require_paths:
208
+ - lib
209
+ required_ruby_version: !ruby/object:Gem::Requirement
210
+ none: false
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ hash: 3
215
+ segments:
216
+ - 0
217
+ version: "0"
218
+ required_rubygems_version: !ruby/object:Gem::Requirement
219
+ none: false
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ hash: 3
224
+ segments:
225
+ - 0
226
+ version: "0"
227
+ requirements: []
228
+
229
+ rubyforge_project:
230
+ rubygems_version: 1.6.2
231
+ signing_key:
232
+ specification_version: 3
233
+ summary: Very simple caching for your ActiveRecord models.
234
+ test_files: []
235
+