prosto_cache 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +5 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +47 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/lib/prosto_cache.rb +139 -0
- data/spec/prosto_cache_spec.rb +120 -0
- data/spec/spec_helper.rb +12 -0
- data/vendor/cache/diff-lcs-1.1.2.gem +0 -0
- data/vendor/cache/git-1.2.5.gem +0 -0
- data/vendor/cache/hashie-1.0.0.gem +0 -0
- data/vendor/cache/jeweler-1.6.0.gem +0 -0
- data/vendor/cache/rake-0.8.7.gem +0 -0
- data/vendor/cache/rcov-0.9.9.gem +0 -0
- data/vendor/cache/reek-1.2.8.gem +0 -0
- data/vendor/cache/roodi-2.1.0.gem +0 -0
- data/vendor/cache/rspec-2.3.0.gem +0 -0
- data/vendor/cache/rspec-core-2.3.1.gem +0 -0
- data/vendor/cache/rspec-expectations-2.3.0.gem +0 -0
- data/vendor/cache/rspec-mocks-2.3.0.gem +0 -0
- data/vendor/cache/ruby2ruby-1.2.5.gem +0 -0
- data/vendor/cache/ruby_parser-2.0.6.gem +0 -0
- data/vendor/cache/sexp_processor-3.0.5.gem +0 -0
- data/vendor/cache/yard-0.6.8.gem +0 -0
- metadata +235 -0
data/.document
ADDED
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
|
data/lib/prosto_cache.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|
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
|
+
|