cachetastic 3.0.5.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ .DS_Store
2
+ pkg
3
+ .gem
4
+ doc
5
+ *.db
6
+ *.log
7
+ *.log
8
+ .DS_Store
9
+ doc
10
+ tmp
11
+ pkg
12
+ *.gem
13
+ *.pid
14
+ coverage
15
+ coverage.data
16
+ build/*
17
+ *.pbxuser
18
+ *.mode1v3
19
+ .svn
20
+ profile
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cachetastic.gemspec
4
+ gemspec
5
+
6
+ gem 'memcache-client'
7
+ gem 'rspec'
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cachetastic (3.1.0)
5
+ activesupport
6
+ configatron
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (3.2.11)
12
+ i18n (~> 0.6)
13
+ multi_json (~> 1.0)
14
+ configatron (2.9.1)
15
+ yamler (>= 0.1.0)
16
+ diff-lcs (1.1.3)
17
+ i18n (0.6.1)
18
+ memcache-client (1.8.5)
19
+ multi_json (1.5.0)
20
+ rake (10.0.3)
21
+ rspec (2.12.0)
22
+ rspec-core (~> 2.12.0)
23
+ rspec-expectations (~> 2.12.0)
24
+ rspec-mocks (~> 2.12.0)
25
+ rspec-core (2.12.2)
26
+ rspec-expectations (2.12.1)
27
+ diff-lcs (~> 1.1.3)
28
+ rspec-mocks (2.12.1)
29
+ yamler (0.1.0)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ cachetastic!
36
+ memcache-client
37
+ rake
38
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Mark Bates
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,4 +1,4 @@
1
- =What is Cachetastic?
1
+ h1. What is Cachetastic?
2
2
 
3
3
  Cachetastic is an incredibly easy to use and administer caching framework. Just because it is easy to use, does not mean that it is light with features. Cachetastic allows you to create classes that extend <code>Cachetastic::Cache</code>, configure them each individually, and much more.
4
4
 
@@ -6,12 +6,13 @@ Unlike other systems each cache in your system can use different backends via th
6
6
 
7
7
  Adapters are easy to write, so if the built in adapters don't float your boat, you can easily knock one off in short order.
8
8
 
9
- ==Configuration:
9
+ h2. Configuration:
10
10
 
11
11
  Configuration of Cachetastic is done using the Configatron gem. I would recommend reading the documentation on it first, hcodep://configatron.mackframework.com, before continuing.
12
12
 
13
13
  All configuration settings hang off of the <code>cachetastic</code> namespace on <code>configatron</code>. The default settings all hang off the <code>defaults</code> namespace on the <code>cachetastic</code> namespace, as shown below:
14
14
 
15
+ <pre><code>
15
16
  # This will write detailed information to the logger.
16
17
  configatron.cachetastic.defaults.debug = false
17
18
 
@@ -44,25 +45,31 @@ All configuration settings hang off of the <code>cachetastic</code> namespace on
44
45
  log_2 = Logger.new("log/cachetastic.log")
45
46
  log_2.level = Logger::ERROR
46
47
  configatron.cachetastic.defaults.logger = [log_1, log_2]
48
+ </code></pre>
47
49
 
48
50
  Overriding settings per cache is very simple. Let's take the following two caches:
49
51
 
52
+ <pre><code>
50
53
  class UserCache < Cachetastic::Cache
51
54
  end
52
55
 
53
56
  class Admin::UserCache < Cachetastic::Cache
54
57
  end
58
+ </code></pre>
55
59
 
56
60
  If we wanted to set the <code>UserCache</code> to use the <code>Cachetastic::Adapters::File</code> adapter and we wanted to set the adapter for
57
61
  the <code>Admin::UserCache</code> to use <code>Cachetastic::Adapters::Memcached</code>, we would configure them like such:
58
62
 
63
+ <pre><code>
59
64
  configatron.cachetastic.user_cache.adapter = Cachetastic::Adapters::File
60
65
  configatron.cachetastic.admin.user_cache.adapter = Cachetastic::Adapters::Memcached
66
+ </code></pre>
61
67
 
62
68
  In this scenario we have changed the adapters for each of the classes. All of the other default settings will remain intact for each of those classes. This makes it incredibly easy to just change the one parameter you need, and not have to reset them all.
63
69
 
64
- ==Examples:
70
+ h2. Examples:
65
71
 
72
+ <pre><code>
66
73
  class MyAwesomeCache < Cachetastic::Cache
67
74
  end
68
75
 
@@ -83,3 +90,4 @@ In this scenario we have changed the adapters for each of the classes. All of th
83
90
 
84
91
  MyAwesomeCache.get(1, 2, 4) # => 8
85
92
  MyAwesomeCache.get(1, 4, 4) # => 8
93
+ </code></pre>
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ desc "Run tests"
6
+ task :default do
7
+ system "bundle exec rspec"
8
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cachetastic/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "cachetastic"
8
+ gem.version = Cachetastic::VERSION
9
+ gem.authors = ["Mark Bates"]
10
+ gem.email = ["mark@markbates.com"]
11
+ gem.description = %q{A very simple, yet very powerful caching framework for Ruby.}
12
+ gem.summary = %q{A very simple, yet very powerful caching framework for Ruby.}
13
+ gem.homepage = ""
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_development_dependency "rake"
22
+ gem.add_dependency "configatron"
23
+ gem.add_dependency "activesupport"
24
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ module Cachetastic
2
+ VERSION = "3.1.0"
3
+ end
data/lib/cachetastic.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  require 'configatron'
2
2
  require 'logger'
3
- require 'active_support'
3
+ require 'active_support/core_ext'
4
4
  require 'fileutils'
5
- require 'memcache'
5
+ begin
6
+ require 'memcache'
7
+ rescue Exception => e
8
+ end
6
9
 
7
10
  Dir.glob(File.join(File.dirname(__FILE__), 'cachetastic', '**/*.rb')).sort.each do |f|
8
11
  require File.expand_path(f)
@@ -0,0 +1,206 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ class CarCache < Cachetastic::Cache
4
+ end
5
+
6
+ describe Cachetastic::Adapters do
7
+
8
+ describe 'build' do
9
+
10
+ it 'should build and a return an Adapter for a Class' do
11
+ adp = Cachetastic::Adapters.build(CarCache)
12
+ adp.should_not be_nil
13
+ adp.should be_kind_of(Cachetastic::Adapters::LocalMemory)
14
+ adp.klass.should be(CarCache)
15
+ configatron.temp do
16
+ configatron.cachetastic.car_cache.adapter = Cachetastic::Adapters::Memcached
17
+ adp = Cachetastic::Adapters.build(CarCache)
18
+ adp.should_not be_nil
19
+ adp.should be_kind_of(Cachetastic::Adapters::Memcached)
20
+ adp.klass.should be(CarCache)
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ describe 'Base' do
27
+
28
+ describe 'transform_key' do
29
+
30
+ it 'should pass the key right through' do
31
+ adapter = Cachetastic::Adapters::Base.new(CarCache)
32
+ adapter.transform_key('$*...123()%~q').should == '$*...123()%~q'
33
+ end
34
+
35
+ end
36
+
37
+ describe 'marshal' do
38
+
39
+ it 'should return the object untouched when set to :none' do
40
+ configatron.temp do
41
+ configatron.cachetastic.defaults.marshal_method = :none
42
+ adapter = Cachetastic::Adapters::Base.new(CarCache)
43
+ adapter.marshal('foo').should == 'foo'
44
+ end
45
+ end
46
+
47
+ it 'should return the object as yaml when set to :yaml' do
48
+ configatron.temp do
49
+ configatron.cachetastic.defaults.marshal_method = :yaml
50
+ adapter = Cachetastic::Adapters::Base.new(CarCache)
51
+ adapter.marshal('foo').should == YAML.dump('foo')
52
+ end
53
+ end
54
+
55
+ it 'should return the object as a ruby serialized object when set to :ruby' do
56
+ configatron.temp do
57
+ configatron.cachetastic.defaults.marshal_method = :ruby
58
+ adapter = Cachetastic::Adapters::Base.new(CarCache)
59
+ adapter.marshal('foo').should == Marshal.dump('foo')
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ describe 'unmarshal' do
66
+
67
+ it 'should return the object untouched when set to :none' do
68
+ configatron.temp do
69
+ configatron.cachetastic.defaults.marshal_method = :none
70
+ adapter = Cachetastic::Adapters::Base.new(CarCache)
71
+ adapter.unmarshal('foo').should == 'foo'
72
+ end
73
+ end
74
+
75
+ it 'should return the yaml as the object when set to :yaml' do
76
+ configatron.temp do
77
+ configatron.cachetastic.defaults.marshal_method = :yaml
78
+ adapter = Cachetastic::Adapters::Base.new(CarCache)
79
+ adapter.unmarshal(YAML.dump('foo')).should == 'foo'
80
+ end
81
+ end
82
+
83
+ it 'should return the ruby serialized object as the original object when set to :ruby' do
84
+ configatron.temp do
85
+ configatron.cachetastic.defaults.marshal_method = :ruby
86
+ adapter = Cachetastic::Adapters::Base.new(CarCache)
87
+ adapter.unmarshal(Marshal.dump('foo')).should == 'foo'
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ ['LocalMemory', 'File', 'Memcached'].each do |adapter|
96
+
97
+ describe "#{adapter} (Common)" do
98
+
99
+ before(:each) do
100
+ configatron.cachetastic.defaults.adapter = "Cachetastic::Adapters::#{adapter}".constantize
101
+ CarCache.clear_adapter!
102
+ CarCache.set(:vw, 'Rabbit')
103
+ end
104
+
105
+ after(:each) do
106
+ CarCache.expire_all
107
+ configatron.cachetastic.defaults.adapter = Cachetastic::Adapters::LocalMemory
108
+ end
109
+
110
+ describe 'get' do
111
+
112
+ it 'should get an object from the cache' do
113
+ CarCache.get(:vw).should == 'Rabbit'
114
+ end
115
+
116
+ it 'should return nil if the object is not in the cache' do
117
+ CarCache.get(:audi).should be_nil
118
+ end
119
+
120
+ it 'should run a block if the object is nil' do
121
+ lambda {
122
+ CarCache.get(:audi) do
123
+ raise Cachetastic::BlockError.new
124
+ end
125
+ }.should raise_error(Cachetastic::BlockError)
126
+ end
127
+
128
+ it 'should run a block if the object is empty' do
129
+ lambda {
130
+ CarCache.set(:audi, [])
131
+ CarCache.get(:audi) do
132
+ raise Cachetastic::BlockError.new
133
+ end
134
+ }.should raise_error(Cachetastic::BlockError)
135
+ end
136
+
137
+ it 'should run a block if the object is blank' do
138
+ lambda {
139
+ CarCache.set(:audi, '')
140
+ CarCache.get(:audi) do
141
+ raise Cachetastic::BlockError.new
142
+ end
143
+ }.should raise_error(Cachetastic::BlockError)
144
+ end
145
+
146
+ end
147
+
148
+ describe 'set' do
149
+
150
+ it 'should set an object into the cache' do
151
+ CarCache.get(:bmw).should be_nil
152
+ CarCache.set(:bmw, 'Beamer!')
153
+ CarCache.get(:bmw).should_not be_nil
154
+ end
155
+
156
+ it 'should set an object into the cache with an expiry' do
157
+ CarCache.get(:bmw).should be_nil
158
+ CarCache.set(:bmw, 'Beamer!', 1)
159
+ CarCache.get(:bmw).should_not be_nil
160
+ sleep(2)
161
+ CarCache.get(:bmw).should be_nil
162
+ end
163
+
164
+ end
165
+
166
+ describe 'delete' do
167
+
168
+ it 'should delete an object from the cache' do
169
+ CarCache.get(:bmw).should be_nil
170
+ CarCache.set(:bmw, 'Beamer!')
171
+ CarCache.get(:bmw).should_not be_nil
172
+ CarCache.delete(:bmw)
173
+ CarCache.get(:bmw).should be_nil
174
+ end
175
+
176
+ end
177
+
178
+ describe 'expire_all' do
179
+
180
+ it 'should expire all objects in the cache' do
181
+ CarCache.get(:vw).should == 'Rabbit'
182
+ CarCache.expire_all
183
+ CarCache.get(:vw).should be_nil
184
+ end
185
+
186
+ end
187
+
188
+ describe 'retry' do
189
+
190
+ it 'should retry if there is an exception' do
191
+ CarCache.should_receive(:clear_adapter!).twice
192
+ lambda {
193
+ CarCache.get(:audi) do
194
+ raise Cachetastic::BlockError.new
195
+ end
196
+ }.should raise_error(Cachetastic::BlockError)
197
+ end
198
+
199
+ end
200
+
201
+ end
202
+
203
+
204
+ end
205
+
206
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ class AnimalCache < Cachetastic::Cache
4
+ end
5
+
6
+ describe Cachetastic::Adapters::File do
7
+
8
+ describe 'transform_key' do
9
+
10
+ it 'should make the key file system safe' do
11
+ base = Cachetastic::Adapters::File.new(AnimalCache)
12
+ base.transform_key('$*...123()%~q').should == '09677cd81f84c4f31d25450b5e8b1362ffa8775a'
13
+ end
14
+
15
+ end
16
+
17
+ describe 'file_path' do
18
+
19
+ it 'should return a proper file path for the key' do
20
+ base = Cachetastic::Adapters::File.new(AnimalCache)
21
+ base.file_path('09677cd81f84c4f31d25450b5e8b1362ffa8775a').should == File.join(FileUtils.pwd, 'cachetastic', 'animal_cache', '978e', '6d2a', 'd1d2', '4420', '3c56', '98ca', '9dea', '3a58', '4cf9', '05b2', 'cache.data')
22
+ end
23
+
24
+ end
25
+
26
+ describe 'expire_all' do
27
+
28
+ it 'should delete the directory and all sub directories when called' do
29
+ configatron.temp do
30
+ configatron.cachetastic.defaults.adapter = Cachetastic::Adapters::File
31
+ base_path = File.join(AnimalCache.adapter.storage_path, 'animal_cache')
32
+ FileUtils.rm_rf(base_path)
33
+ File.should_not be_exist(base_path)
34
+ AnimalCache.set('bear', 'Grizzly Bear!')
35
+ AnimalCache.get('bear').should == 'Grizzly Bear!'
36
+ File.should be_exist(base_path)
37
+ File.should be_exist(AnimalCache.adapter.file_path('bear'))
38
+ AnimalCache.expire_all
39
+ File.should_not be_exist(base_path)
40
+ File.should_not be_exist(AnimalCache.adapter.file_path(AnimalCache.adapter.transform_key('bear')))
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Cachetastic::Adapters::LocalMemory do
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Cachetastic::Adapters::Memcached do
4
+
5
+ end
@@ -0,0 +1,137 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class SimpleCache < Cachetastic::Cache
4
+ end
5
+
6
+ describe Cachetastic::Cache do
7
+
8
+ before(:each) do
9
+ configatron.cachetastic.defaults.adapter = Cachetastic::Adapters::LocalMemory
10
+ end
11
+
12
+ describe 'get' do
13
+
14
+ it 'should execute a block if the result is nil' do
15
+ val = SimpleCache.get(:mark)
16
+ val.should be_nil
17
+
18
+ val = SimpleCache.get(:mark) do |key|
19
+ SimpleCache.set(:mark, "Hello #{key}")
20
+ end
21
+ val.should_not be_nil
22
+ val.should == 'Hello mark'
23
+
24
+ val = SimpleCache.get(:mark)
25
+ val.should_not be_nil
26
+ val.should == 'Hello mark'
27
+ end
28
+
29
+ end
30
+
31
+ describe 'adapter' do
32
+
33
+ it 'should return the adapter for the cache' do
34
+ SimpleCache.clear_adapter!
35
+ SimpleCache.adapter.should_not be_nil
36
+ SimpleCache.adapter.should be_kind_of(Cachetastic::Adapters::LocalMemory)
37
+ configatron.temp do
38
+ SimpleCache.clear_adapter!
39
+ configatron.cachetastic.defaults.adapter = Cachetastic::Adapters::File
40
+ SimpleCache.adapter.should be_kind_of(Cachetastic::Adapters::File)
41
+ end
42
+ end
43
+
44
+ it 'should retain the adapter for the life of the class' do
45
+ adapter = SimpleCache.adapter
46
+ adapter.should_not be_nil
47
+ 3.times do
48
+ adapter.should === SimpleCache.adapter
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ describe 'cache_klass' do
55
+
56
+ it 'should return the class constant by default' do
57
+ SimpleCache.cache_klass.should == SimpleCache
58
+ end
59
+
60
+ end
61
+
62
+ describe 'calculate_expiry_time' do
63
+
64
+ it 'should properly +/- swing to the expiry time' do
65
+ configatron.temp do
66
+ configatron.cachetastic.defaults.expiry_swing = 15
67
+ configatron.cachetastic.defaults.default_expiry = 60
68
+ SimpleCache.class_eval do
69
+ class << self
70
+ public :calculate_expiry_time
71
+ end
72
+ end
73
+ 10.times do
74
+ SimpleCache.calculate_expiry_time(60).should >= 45
75
+ SimpleCache.calculate_expiry_time(60).should <= 75
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+
83
+ describe 'logging' do
84
+
85
+ before(:each) do
86
+ Time.stub!(:now).and_return(Time.at(0))
87
+ @logger = mock(Logger.new(STDOUT))
88
+ configatron.cachetastic.simple_cache.debug = true
89
+ end
90
+
91
+ describe 'get' do
92
+
93
+ it 'should log a get call' do
94
+ SimpleCache.logger.stub!(:debug)
95
+ SimpleCache.logger.should_receive(:debug).with(:starting, :get, 'SimpleCache', 1)
96
+ SimpleCache.logger.should_receive(:debug).with(:finished, :get, 'SimpleCache', 1, 0.0, '')
97
+ SimpleCache.get(1)
98
+ end
99
+
100
+ end
101
+
102
+ describe 'set' do
103
+
104
+ it 'should log a set call' do
105
+ SimpleCache.logger.stub!(:debug)
106
+ SimpleCache.logger.should_receive(:debug).with(:starting, :set, 'SimpleCache', 1)
107
+ SimpleCache.logger.should_receive(:debug).with(:finished, :set, 'SimpleCache', 1, 0.0, "[String]\t[Size = 3]\t\"foo\"")
108
+ SimpleCache.set(1, 'foo')
109
+ end
110
+
111
+ end
112
+
113
+ describe 'delete' do
114
+
115
+ it 'should log a delete call' do
116
+ SimpleCache.logger.stub!(:debug)
117
+ SimpleCache.logger.should_receive(:debug).with(:starting, :delete, 'SimpleCache', 1)
118
+ SimpleCache.logger.should_receive(:debug).with(:finished, :delete, 'SimpleCache', 1, 0.0, '')
119
+ SimpleCache.delete(1)
120
+ end
121
+
122
+ end
123
+
124
+ describe 'expire_all' do
125
+
126
+ it 'should log an expire_all' do
127
+ SimpleCache.logger.stub!(:debug)
128
+ SimpleCache.logger.should_receive(:debug).with(:starting, :expire_all, 'SimpleCache', nil)
129
+ SimpleCache.logger.should_receive(:debug).with(:finished, :expire_all, 'SimpleCache', nil, 0.0, '')
130
+ SimpleCache.expire_all
131
+ end
132
+
133
+ end
134
+
135
+ end
136
+
137
+ end
@@ -0,0 +1,155 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class MyObject
4
+ include Cachetastic::Cacheable
5
+ end
6
+
7
+ module My
8
+ module Namespaced
9
+ class Thing
10
+ include Cachetastic::Cacheable
11
+ end
12
+ class Animal
13
+ include Cachetastic::Cacheable
14
+ end
15
+ end
16
+ end
17
+
18
+ describe Cachetastic::Cacheable do
19
+
20
+ before(:each) do
21
+ MyObject.cache_class.clear_adapter!
22
+ end
23
+
24
+ after(:each) do
25
+ end
26
+
27
+ describe 'cache_class' do
28
+
29
+ it 'should create a new cache class if one doesnt already exist' do
30
+ MyObject.cache_class.should == Cachetastic::Cacheable::MyObjectCache
31
+ Cachetastic::Cacheable::MyObjectCache.new.should be_kind_of(Cachetastic::Cache)
32
+ end
33
+
34
+ it 'should handle namespaced classes correctly' do
35
+ Cachetastic::Cacheable.should_not be_const_defined(:My_Namespaced_ThingCache)
36
+ My::Namespaced::Thing.cache_class.should == Cachetastic::Cacheable::My_Namespaced_ThingCache
37
+ Cachetastic::Cacheable.should be_const_defined(:My_Namespaced_ThingCache)
38
+ Cachetastic::Cacheable::My_Namespaced_ThingCache.new.should be_kind_of(Cachetastic::Cache)
39
+ end
40
+
41
+ it 'should override cache_klass to return the name of the original class, not the generated class' do
42
+ My::Namespaced::Animal.cache_class.cache_klass.should == My::Namespaced::Animal
43
+ end
44
+
45
+ it 'should use the original class name for looking up settings' do
46
+ configatron.temp do
47
+ configatron.cachetastic.my_object.adapter = Cachetastic::Adapters::Memcached
48
+ MyObject.cache_class.adapter.should be_instance_of(Cachetastic::Adapters::Memcached)
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ describe 'cacher' do
55
+
56
+ it 'should retreive from, or cache, from the cache based on the key at the instance level' do
57
+ obj = My::Namespaced::Animal.new
58
+ obj.instance_eval do
59
+ def roar
60
+ cacher('roar') do
61
+ "roar!! #{rand}"
62
+ end
63
+ end
64
+ end
65
+ obj.roar.should match(/^roar!! (\d{1}\.{1}\d+)$/)
66
+ val = obj.roar
67
+ 5.times do
68
+ obj.roar.should == val
69
+ end
70
+ Cachetastic::Cacheable::My_Namespaced_AnimalCache.get('roar').should == val
71
+ end
72
+
73
+ it 'should retreive from, or cache, from the cache based on the key at the class level' do
74
+ My::Namespaced::Thing.class_eval do
75
+ def self.shout
76
+ cacher('shout') do
77
+ "shout!! #{rand}"
78
+ end
79
+ end
80
+ end
81
+ My::Namespaced::Thing.shout.should match(/^shout!! (\d{1}\.{1}\d+)$/)
82
+ val = My::Namespaced::Thing.shout
83
+ 5.times do
84
+ My::Namespaced::Thing.shout.should == val
85
+ end
86
+ Cachetastic::Cacheable::My_Namespaced_ThingCache.get('shout').should == val
87
+ end
88
+
89
+ it 'should return the object, not the memcached response' do
90
+ configatron.temp do
91
+ configatron.cachetastic.my_object.adapter = Cachetastic::Adapters::Memcached
92
+ MyObject.class_eval do
93
+ def self.say_random
94
+ cacher('say_random') do
95
+ "Random!! #{rand}"
96
+ end
97
+ end
98
+ end
99
+ MyObject.cache_class.adapter.should be_instance_of(Cachetastic::Adapters::Memcached)
100
+ r = MyObject.say_random
101
+ r.should match(/^Random!! (\d{1}\.{1}\d+)$/)
102
+ 5.times do
103
+ r.should == MyObject.say_random
104
+ end
105
+ end
106
+ end
107
+
108
+ end
109
+
110
+ describe 'cache_self' do
111
+
112
+ it 'should cache itself using the cachetastic_key method as the key' do
113
+ MyObject.cache_class
114
+ Cachetastic::Cacheable::MyObjectCache.get(1).should be_nil
115
+
116
+ obj = MyObject.new
117
+ obj.instance_eval do
118
+ def cachetastic_key
119
+ 1
120
+ end
121
+ def value
122
+ @value ||= rand
123
+ end
124
+ end
125
+
126
+ obj.cache_self
127
+ Cachetastic::Cacheable::MyObjectCache.get(1).should_not be_nil
128
+ Cachetastic::Cacheable::MyObjectCache.get(1).value.should == obj.value
129
+ end
130
+
131
+ end
132
+
133
+ describe 'uncache_self' do
134
+
135
+ it 'should cache itself using the cachetastic_key method as the key' do
136
+ MyObject.cache_class
137
+ Cachetastic::Cacheable::MyObjectCache.get(2).should be_nil
138
+
139
+ obj = MyObject.new
140
+ obj.instance_eval do
141
+ def cachetastic_key
142
+ 2
143
+ end
144
+ end
145
+
146
+ obj.cache_self
147
+ Cachetastic::Cacheable::MyObjectCache.get(2).should_not be_nil
148
+
149
+ obj.uncache_self
150
+ Cachetastic::Cacheable::MyObjectCache.get(2).should be_nil
151
+ end
152
+
153
+ end
154
+
155
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Cachetastic::Logger do
4
+
5
+ before(:each) do
6
+ Time.stub!(:now).and_return(Time.at(0))
7
+ @logger = mock(Logger.new(STDOUT))
8
+ end
9
+
10
+ [:fatal, :error, :warn, :info, :debug].each do |meth|
11
+
12
+ describe meth do
13
+
14
+ it "should call the underlying #{meth} method" do
15
+ @logger.should_receive(meth).with("[CACHE] [#{meth.to_s.upcase}]\t12/31/69 19:00:00\tHi!")
16
+
17
+ c_logger = Cachetastic::Logger.new(@logger)
18
+ c_logger.send(meth, 'Hi!')
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Cachetastic::Cache::StoreObject do
4
+
5
+ describe 'expired?' do
6
+
7
+ it 'should return true if the object is expired' do
8
+ obj = Cachetastic::Cache::StoreObject.new(nil, nil, 1.minute.ago)
9
+ obj.should be_expired
10
+ end
11
+
12
+ it 'should return false if the object is not expired' do
13
+ obj = Cachetastic::Cache::StoreObject.new(nil, nil, 1.minute.from_now)
14
+ obj.should_not be_expired
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,28 @@
1
+ ENV["RACK_ENV"] ||= "test"
2
+
3
+ require 'bundler/setup'
4
+
5
+ require 'cachetastic' # and any other gems you need
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ config.before(:all) do
10
+
11
+ end
12
+
13
+ config.after(:all) do
14
+
15
+ end
16
+
17
+ config.before(:each) do
18
+
19
+ end
20
+
21
+ config.after(:each) do
22
+
23
+ end
24
+
25
+ end
26
+
27
+ class Cachetastic::BlockError < StandardError
28
+ end
metadata CHANGED
@@ -1,57 +1,79 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: cachetastic
3
- version: !ruby/object:Gem::Version
4
- version: 3.0.5.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.1.0
5
+ prerelease:
5
6
  platform: ruby
6
- authors:
7
- - markbates
7
+ authors:
8
+ - Mark Bates
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
-
12
- date: 2010-02-03 00:00:00 -05:00
13
- default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
12
+ date: 2013-01-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
16
31
  name: configatron
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
17
38
  type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 2.3.2
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: memcache-client
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.7.4
34
- version:
35
- - !ruby/object:Gem::Dependency
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
36
47
  name: activesupport
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
37
54
  type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 2.3.2
44
- version:
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
45
62
  description: A very simple, yet very powerful caching framework for Ruby.
46
- email: mark@markbates.com
63
+ email:
64
+ - mark@markbates.com
47
65
  executables: []
48
-
49
66
  extensions: []
50
-
51
- extra_rdoc_files:
52
- - README
53
- - LICENSE
54
- files:
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - LICENSE.txt
73
+ - README.md
74
+ - Rakefile
75
+ - cachetastic.gemspec
76
+ - lib/cachetastic.rb
55
77
  - lib/cachetastic/adapters/base.rb
56
78
  - lib/cachetastic/adapters/file.rb
57
79
  - lib/cachetastic/adapters/local_memory.rb
@@ -61,36 +83,48 @@ files:
61
83
  - lib/cachetastic/extensions/string.rb
62
84
  - lib/cachetastic/logger.rb
63
85
  - lib/cachetastic/store_object.rb
64
- - lib/cachetastic.rb
65
- - README
66
- - LICENSE
67
- has_rdoc: true
68
- homepage: http://www.metabates.com
69
- licenses: []
70
-
86
+ - lib/cachetastic/version.rb
87
+ - spec/cachetastic/adapters/base_spec.rb
88
+ - spec/cachetastic/adapters/file_spec.rb
89
+ - spec/cachetastic/adapters/local_memory_spec.rb
90
+ - spec/cachetastic/adapters/memcached_spec.rb
91
+ - spec/cachetastic/cache_spec.rb
92
+ - spec/cachetastic/cacheable_spec.rb
93
+ - spec/cachetastic/logger_spec.rb
94
+ - spec/cachetastic/store_object_spec.rb
95
+ - spec/spec_helper.rb
96
+ homepage: ''
97
+ licenses:
98
+ - MIT
71
99
  post_install_message:
72
100
  rdoc_options: []
73
-
74
- require_paths:
101
+ require_paths:
75
102
  - lib
76
- required_ruby_version: !ruby/object:Gem::Requirement
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- version: "0"
81
- version:
82
- required_rubygems_version: !ruby/object:Gem::Requirement
83
- requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- version: "0"
87
- version:
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
88
115
  requirements: []
89
-
90
- rubyforge_project: magrathea
91
- rubygems_version: 1.3.5
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.24
92
118
  signing_key:
93
119
  specification_version: 3
94
120
  summary: A very simple, yet very powerful caching framework for Ruby.
95
- test_files: []
96
-
121
+ test_files:
122
+ - spec/cachetastic/adapters/base_spec.rb
123
+ - spec/cachetastic/adapters/file_spec.rb
124
+ - spec/cachetastic/adapters/local_memory_spec.rb
125
+ - spec/cachetastic/adapters/memcached_spec.rb
126
+ - spec/cachetastic/cache_spec.rb
127
+ - spec/cachetastic/cacheable_spec.rb
128
+ - spec/cachetastic/logger_spec.rb
129
+ - spec/cachetastic/store_object_spec.rb
130
+ - spec/spec_helper.rb
data/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- The MIT License
2
-
3
- Copyright (c) 2009 Mark Bates
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.