cachetastic-three 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +21 -0
- data/README +89 -0
- data/doc/classes/Cachetastic/Adapters.html +180 -0
- data/doc/classes/Cachetastic/Adapters/Base.html +419 -0
- data/doc/classes/Cachetastic/Adapters/File.html +135 -0
- data/doc/classes/Cachetastic/Adapters/LocalMemory.html +125 -0
- data/doc/classes/Cachetastic/Adapters/Memcached.html +193 -0
- data/doc/classes/Cachetastic/Cache.html +425 -0
- data/doc/classes/Cachetastic/Cacheable.html +255 -0
- data/doc/classes/Cachetastic/Cacheable/ClassAndInstanceMethods.html +290 -0
- data/doc/classes/Cachetastic/Cacheable/ClassOnlyMethods.html +197 -0
- data/doc/classes/Cachetastic/Logger.html +186 -0
- data/doc/created.rid +1 -0
- data/doc/files/LICENSE.html +132 -0
- data/doc/files/README.html +222 -0
- data/doc/files/lib/cachetastic/adapters/base_rb.html +101 -0
- data/doc/files/lib/cachetastic/adapters/file_rb.html +101 -0
- data/doc/files/lib/cachetastic/adapters/local_memory_rb.html +101 -0
- data/doc/files/lib/cachetastic/adapters/memcached_rb.html +101 -0
- data/doc/files/lib/cachetastic/cache_rb.html +101 -0
- data/doc/files/lib/cachetastic/cacheable_rb.html +101 -0
- data/doc/files/lib/cachetastic/extensions/string_rb.html +108 -0
- data/doc/files/lib/cachetastic/logger_rb.html +101 -0
- data/doc/files/lib/cachetastic/store_object_rb.html +101 -0
- data/doc/files/lib/cachetastic_rb.html +112 -0
- data/doc/fr_class_index.html +36 -0
- data/doc/fr_file_index.html +38 -0
- data/doc/fr_method_index.html +52 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/cachetastic.rb +20 -0
- data/lib/cachetastic/adapters/base.rb +178 -0
- data/lib/cachetastic/adapters/file.rb +66 -0
- data/lib/cachetastic/adapters/local_memory.rb +37 -0
- data/lib/cachetastic/adapters/memcached.rb +114 -0
- data/lib/cachetastic/cache.rb +165 -0
- data/lib/cachetastic/cacheable.rb +202 -0
- data/lib/cachetastic/extensions/string.rb +8 -0
- data/lib/cachetastic/logger.rb +49 -0
- data/lib/cachetastic/store_object.rb +22 -0
- metadata +122 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
module Cachetastic # :nodoc:
|
2
|
+
module Adapters
|
3
|
+
# An adapter to cache objects to the file system.
|
4
|
+
#
|
5
|
+
# This adapter supports the following configuration settings,
|
6
|
+
# in addition to the default settings:
|
7
|
+
#
|
8
|
+
# configatron.cachetastic.defaults.storage_path = ::File.join(FileUtils.pwd, 'cachetastic')
|
9
|
+
# configatron.cachetastic.defaults.marshal_method = :yaml
|
10
|
+
#
|
11
|
+
# The <tt>storage_path</tt> setting defines the path to where cached
|
12
|
+
# objects are written to on disk.
|
13
|
+
#
|
14
|
+
# See <tt>Cachetastic::Adapters::Base</tt> for a list of public API
|
15
|
+
# methods.
|
16
|
+
class File < Cachetastic::Adapters::Base
|
17
|
+
|
18
|
+
def initialize(klass) # :nodoc:
|
19
|
+
define_accessor(:storage_path)
|
20
|
+
self.storage_path = ::File.join(FileUtils.pwd, 'cachetastic')
|
21
|
+
super
|
22
|
+
self.marshal_method = :yaml if self.marshal_method == :none
|
23
|
+
@_file_paths = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(key) # :nodoc:
|
27
|
+
path = file_path(key)
|
28
|
+
val = nil
|
29
|
+
val = ::File.read(path) if ::File.exists?(path)
|
30
|
+
return val
|
31
|
+
end # get
|
32
|
+
|
33
|
+
def set(key, value, expiry_time = configatron.cachetastic.defaults.default_expiry) # :nodoc:
|
34
|
+
so = Cachetastic::Cache::StoreObject.new(key, value, expiry_time.from_now)
|
35
|
+
path = file_path(key)
|
36
|
+
::File.open(path, 'w') {|f| f.write marshal(so)}
|
37
|
+
value
|
38
|
+
end # set
|
39
|
+
|
40
|
+
def delete(key) # :nodoc:
|
41
|
+
FileUtils.rm(file_path(key))
|
42
|
+
end # delete
|
43
|
+
|
44
|
+
def expire_all # :nodoc:
|
45
|
+
@_file_paths = {}
|
46
|
+
::FileUtils.rm_rf(::File.join(self.storage_path, klass.name.underscore))
|
47
|
+
return nil
|
48
|
+
end # expire_all
|
49
|
+
|
50
|
+
def transform_key(key) # :nodoc:
|
51
|
+
key.to_s.hexdigest
|
52
|
+
end
|
53
|
+
|
54
|
+
def file_path(key) # :nodoc:
|
55
|
+
path = @_file_paths[key]
|
56
|
+
if path.nil?
|
57
|
+
path = ::File.join(self.storage_path, klass.name.underscore, transform_key(key).scan(/(.{1,4})/).flatten, 'cache.data')
|
58
|
+
@_file_paths[key] = path
|
59
|
+
FileUtils.mkdir_p(::File.dirname(path))
|
60
|
+
end
|
61
|
+
return path
|
62
|
+
end
|
63
|
+
|
64
|
+
end # File
|
65
|
+
end # Adapters
|
66
|
+
end # Cachetastic
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Cachetastic # :nodoc:
|
2
|
+
module Adapters
|
3
|
+
# An adapter to cache objects to memory. It is important to note
|
4
|
+
# that this cache is <b>volatile</b>. If the VM it is running in
|
5
|
+
# shuts down, everything in the cache gets vaporized.
|
6
|
+
#
|
7
|
+
# See <tt>Cachetastic::Adapters::Base</tt> for a list of public API
|
8
|
+
# methods.
|
9
|
+
class LocalMemory < Cachetastic::Adapters::Base
|
10
|
+
|
11
|
+
def initialize(klass) # :nodoc:
|
12
|
+
super
|
13
|
+
@_store = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def get(key) # :nodoc:
|
17
|
+
@_store[key]
|
18
|
+
end # get
|
19
|
+
|
20
|
+
def set(key, value, expiry_time = configatron.cachetastic.defaults.default_expiry) # :nodoc:
|
21
|
+
so = Cachetastic::Cache::StoreObject.new(key, value, expiry_time.from_now)
|
22
|
+
@_store[key] = marshal(so)
|
23
|
+
value
|
24
|
+
end # set
|
25
|
+
|
26
|
+
def delete(key) # :nodoc:
|
27
|
+
@_store.delete(key)
|
28
|
+
end # delete
|
29
|
+
|
30
|
+
def expire_all # :nodoc:
|
31
|
+
@_store = {}
|
32
|
+
return nil
|
33
|
+
end # expire_all
|
34
|
+
|
35
|
+
end # LocalMemory
|
36
|
+
end # Adapters
|
37
|
+
end # Cachetastic
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Cachetastic # :nodoc:
|
2
|
+
module Adapters
|
3
|
+
# An adapter to cache objects to the file system.
|
4
|
+
#
|
5
|
+
# This adapter supports the following configuration settings,
|
6
|
+
# in addition to the default settings:
|
7
|
+
#
|
8
|
+
# configatron.cachetastic.defaults.servers = ['127.0.0.1:11211']
|
9
|
+
# configatron.cachetastic.defaults.mc_options = {:c_threshold => 10_000,
|
10
|
+
# :compression => true,
|
11
|
+
# :debug => false,
|
12
|
+
# :readonly => false,
|
13
|
+
# :urlencode => false}
|
14
|
+
# configatron.cachetastic.delete_delay = 0
|
15
|
+
#
|
16
|
+
# The <tt>servers</tt> setting defines an <tt>Array</tt> of Mecached
|
17
|
+
# servers, represented as "<host>:<port>".
|
18
|
+
#
|
19
|
+
# The <tt>mc_options</tt> setting is a <tt>Hash</tt> of settings required
|
20
|
+
# by Memcached. See the Memcached documentation for more information on
|
21
|
+
# what the settings mean.
|
22
|
+
#
|
23
|
+
# The <tt>delete_delay</tt> setting tells Memcached how long to wait
|
24
|
+
# before it deletes the object. This is not the same as <tt>expiry_time</tt>.
|
25
|
+
# It is only used when the <tt>delete</tt> method is called.
|
26
|
+
#
|
27
|
+
# See <tt>Cachetastic::Adapters::Base</tt> for a list of public API
|
28
|
+
# methods.
|
29
|
+
class Memcached < Cachetastic::Adapters::Base
|
30
|
+
|
31
|
+
def initialize(klass) # :nodoc:
|
32
|
+
define_accessor(:servers)
|
33
|
+
define_accessor(:mc_options)
|
34
|
+
define_accessor(:delete_delay)
|
35
|
+
self.delete_delay = 0
|
36
|
+
self.servers = ['127.0.0.1:11211']
|
37
|
+
self.mc_options = {:c_threshold => 10_000,
|
38
|
+
:compression => true,
|
39
|
+
:debug => false,
|
40
|
+
:readonly => false,
|
41
|
+
:urlencode => false}
|
42
|
+
super
|
43
|
+
connection
|
44
|
+
end
|
45
|
+
|
46
|
+
def get(key) # :nodoc:
|
47
|
+
connection.get(transform_key(key), false)
|
48
|
+
end # get
|
49
|
+
|
50
|
+
def set(key, value, expiry_time = configatron.cachetastic.defaults.default_expiry) # :nodoc:
|
51
|
+
connection.set(transform_key(key), marshal(value), expiry_time, false)
|
52
|
+
end # set
|
53
|
+
|
54
|
+
def delete(key) # :nodoc:
|
55
|
+
connection.delete(transform_key(key), self.delete_delay)
|
56
|
+
end # delete
|
57
|
+
|
58
|
+
def expire_all # :nodoc:
|
59
|
+
increment_version
|
60
|
+
@_mc_connection = nil
|
61
|
+
return nil
|
62
|
+
end # expire_all
|
63
|
+
|
64
|
+
def transform_key(key) # :nodoc:
|
65
|
+
key.to_s.hexdigest
|
66
|
+
end
|
67
|
+
|
68
|
+
# Return <tt>false</tt> if the connection to Memcached is
|
69
|
+
# either <tt>nil</tt> or not active.
|
70
|
+
def valid?
|
71
|
+
return false if @_mc_connection.nil?
|
72
|
+
return false unless @_mc_connection.active?
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
def connection
|
78
|
+
unless @_mc_connection && valid? && @_ns_version == get_version
|
79
|
+
@_mc_connection = MemCache.new(self.servers, self.mc_options.merge(:namespace => namespace))
|
80
|
+
end
|
81
|
+
@_mc_connection
|
82
|
+
end
|
83
|
+
|
84
|
+
def ns_connection
|
85
|
+
unless @_ns_connection
|
86
|
+
@_ns_connection = MemCache.new(self.servers, self.mc_options.merge(:namespace => :namespace_versions))
|
87
|
+
end
|
88
|
+
@_ns_connection
|
89
|
+
end
|
90
|
+
|
91
|
+
def increment_version
|
92
|
+
name = self.klass.name
|
93
|
+
v = get_version
|
94
|
+
ns_connection.set(name, v + 1)
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_version
|
98
|
+
name = self.klass.name
|
99
|
+
v = ns_connection.get(name)
|
100
|
+
if v.nil?
|
101
|
+
ns_connection.set(name, 1)
|
102
|
+
v = 1
|
103
|
+
end
|
104
|
+
v
|
105
|
+
end
|
106
|
+
|
107
|
+
def namespace
|
108
|
+
@_ns_version = get_version
|
109
|
+
"#{self.klass.name}.#{@_ns_version}"
|
110
|
+
end
|
111
|
+
|
112
|
+
end # Memcached
|
113
|
+
end # Adapters
|
114
|
+
end # Cachetastic
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module Cachetastic # :nodoc:
|
2
|
+
# When creating a new 'Cache' this class should be extended.
|
3
|
+
# Once extended you'll only need to override just the methods
|
4
|
+
# that are different for your cache.
|
5
|
+
# class MyAwesomeCache < Cachetastic::Cache
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# MyAwesomeCache.set(1, "One")
|
9
|
+
# MyAwesomeCache.get(1) # => "One"
|
10
|
+
# MyAwesomeCache.update(1, "One!!")
|
11
|
+
# MyAwesomeCache.get(1) # => "One!!"
|
12
|
+
# MyAwesomeCache.delete(1)
|
13
|
+
# MyAwesomeCache.get(1) # => nil
|
14
|
+
#
|
15
|
+
# class MyAwesomeCache < Cachetastic::Cache
|
16
|
+
# class << self
|
17
|
+
# def get(key)
|
18
|
+
# super(key) do
|
19
|
+
# set(key, key * 10)
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# MyAwesomeCache.set(1, "One")
|
26
|
+
# MyAwesomeCache.get(1) # => "One"
|
27
|
+
# MyAwesomeCache.delete(1)
|
28
|
+
# MyAwesomeCache.get(1) # => 10
|
29
|
+
class Cache
|
30
|
+
|
31
|
+
# everything is done at the class level. there won't be any 'instances of it'
|
32
|
+
# using class << self means we don't have to prefix each method with 'self.'
|
33
|
+
class << self
|
34
|
+
|
35
|
+
# Returns an object from the cache for a given key.
|
36
|
+
# If the object comes back as nil and a block is given
|
37
|
+
# that block will be run and the results of the block
|
38
|
+
# will be returned. This can be used to JIT caches, just make
|
39
|
+
# sure in the block to call the set method because the
|
40
|
+
# results of the block are not automatically cached.
|
41
|
+
def get(key, &block)
|
42
|
+
do_with_logging(:get, key) do
|
43
|
+
val = self.adapter.get(key)
|
44
|
+
handle_store_object(key, adapter.unmarshal(val), &block)
|
45
|
+
end
|
46
|
+
end # get
|
47
|
+
|
48
|
+
# Set a particular object info the cache for the given key.
|
49
|
+
#
|
50
|
+
# An optional third parameter sets the expiry time for the object in the cache.
|
51
|
+
# If no expiry_time is passed in then the default expiry_time that has been configured
|
52
|
+
# will be used.
|
53
|
+
#
|
54
|
+
# If there is an the expiry_swing setting is configured it will be +/- to the
|
55
|
+
# expiry time.
|
56
|
+
def set(key, value, expiry_time = nil)
|
57
|
+
do_with_logging(:set, key) do
|
58
|
+
self.adapter.set(key, value, calculate_expiry_time(expiry_time))
|
59
|
+
end
|
60
|
+
end # set
|
61
|
+
|
62
|
+
# Deletes an object from the cache.
|
63
|
+
def delete(key)
|
64
|
+
do_with_logging(:delete, key) do
|
65
|
+
self.adapter.delete(key)
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end # delete
|
69
|
+
|
70
|
+
# Expires all objects for this cache.
|
71
|
+
def expire_all
|
72
|
+
do_with_logging(:expire_all, nil) do
|
73
|
+
self.adapter.expire_all
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end # expire_all
|
77
|
+
|
78
|
+
# Returns the underlying Cachetastic::Adapters::Base for this cache.
|
79
|
+
def adapter
|
80
|
+
unless @_adapter && @_adapter.valid?
|
81
|
+
@_adapter = Cachetastic::Adapters.build(cache_klass)
|
82
|
+
end
|
83
|
+
@_adapter
|
84
|
+
end # adapter
|
85
|
+
|
86
|
+
# Clears the adapter so it can be redefined. This is useful if you have
|
87
|
+
# reconfigured the cache to use a different adapater, or different settings.
|
88
|
+
def clear_adapter!
|
89
|
+
@_adapter = nil
|
90
|
+
end
|
91
|
+
|
92
|
+
def cache_klass # :nodoc:
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the Cachetastic::Logger for this cache.
|
97
|
+
def logger
|
98
|
+
unless @_logger
|
99
|
+
@_logger = Cachetastic::Logger.new(adapter.logger)
|
100
|
+
end
|
101
|
+
@_logger
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
# If the expiry time is set to 60 minutes and the expiry_swing time is set to
|
106
|
+
# 15 minutes, this method will return a number between 45 minutes and 75 minutes.
|
107
|
+
def calculate_expiry_time(expiry_time) # :doc:
|
108
|
+
expiry_time = self.adapter.default_expiry if expiry_time.nil?
|
109
|
+
exp_swing = self.adapter.expiry_swing
|
110
|
+
if exp_swing && exp_swing != 0
|
111
|
+
swing = rand(exp_swing.to_i)
|
112
|
+
case rand(2)
|
113
|
+
when 0
|
114
|
+
expiry_time = (expiry_time.to_i + swing)
|
115
|
+
when 1
|
116
|
+
expiry_time = (expiry_time.to_i - swing)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
expiry_time
|
120
|
+
end
|
121
|
+
|
122
|
+
def handle_store_object(key, val, &block)
|
123
|
+
if val.is_a?(Cachetastic::Cache::StoreObject)
|
124
|
+
if val.expired?
|
125
|
+
self.delete(key)
|
126
|
+
val = nil
|
127
|
+
else
|
128
|
+
val = val.value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
if val.respond_to?(:empty?)
|
133
|
+
val = nil if val.empty?
|
134
|
+
elsif val.respond_to?(:blank?)
|
135
|
+
val = nil if val.blank?
|
136
|
+
end
|
137
|
+
return val unless val.nil?
|
138
|
+
|
139
|
+
val = yield if block_given?
|
140
|
+
return val
|
141
|
+
end
|
142
|
+
|
143
|
+
def do_with_logging(action, key)
|
144
|
+
if adapter.debug?
|
145
|
+
start_time = Time.now
|
146
|
+
logger.debug(:starting, action, cache_klass.name, key)
|
147
|
+
res = yield if block_given?
|
148
|
+
end_time = Time.now
|
149
|
+
str = ''
|
150
|
+
unless res.nil?
|
151
|
+
str = "[#{res.class.name}]"
|
152
|
+
str << "\t[Size = #{res.size}]" if res.respond_to? :size
|
153
|
+
str << "\t" << res.inspect
|
154
|
+
end
|
155
|
+
logger.debug(:finished, action, cache_klass.name, key, (end_time - start_time), str)
|
156
|
+
return res
|
157
|
+
else
|
158
|
+
return yield if block_given?
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
end # class << self
|
163
|
+
|
164
|
+
end # Cache
|
165
|
+
end # Cachetastic
|
@@ -0,0 +1,202 @@
|
|
1
|
+
module Cachetastic # :nodoc:
|
2
|
+
# Include this module into an Object to achieve simplistic Object level caching.
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
# class Person
|
6
|
+
# include Cachetastic::Cacheable
|
7
|
+
#
|
8
|
+
# attr_accessor :name
|
9
|
+
#
|
10
|
+
# def cachetastic_key
|
11
|
+
# self.name
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def always_the_same(x, y)
|
15
|
+
# cacher("always_the_same") do
|
16
|
+
# x + y
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# end
|
21
|
+
module Cacheable
|
22
|
+
|
23
|
+
module ClassAndInstanceMethods
|
24
|
+
# Returns the Cachetastic::Cache object associated with the object.
|
25
|
+
# If a cache hasn't been defined the one will be created on the fly.
|
26
|
+
# The cache for the object is expected to be defined as:
|
27
|
+
# Cachetastic::Cacheable::{CLASS_NAME_HERE}Cache
|
28
|
+
#
|
29
|
+
# Examples:
|
30
|
+
# class Person
|
31
|
+
# include Cachetastic::Cacheable
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# Person.cache_class # => Cachetastic::Cacheable::PersonCache
|
35
|
+
#
|
36
|
+
# class Admin::Person
|
37
|
+
# include Cachetastic::Cacheable
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# Admin::Person.cache_class # => Cachetastic::Cacheable::Admin_PersonCache
|
41
|
+
def cache_class
|
42
|
+
n = self.class.name
|
43
|
+
n = self.name if n == "Class"
|
44
|
+
c_name = "Cachetastic::Cacheable::#{n.gsub('::', '_')}Cache"
|
45
|
+
begin
|
46
|
+
return c_name.constantize
|
47
|
+
rescue NameError => e
|
48
|
+
eval %{
|
49
|
+
class #{c_name} < Cachetastic::Cache
|
50
|
+
|
51
|
+
def self.cache_klass
|
52
|
+
#{n}
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
}
|
57
|
+
return c_name.constantize
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
# How much did I want to call this method cache?? It originally was that, but
|
63
|
+
# in Rails 2.0 they decided to use that name, so I had to rename this method.
|
64
|
+
# This method will attempt to get an object from the cache for a given key.
|
65
|
+
# If the object is nil and a block is given the block will be run, and the results
|
66
|
+
# of the block will be automatically cached.
|
67
|
+
#
|
68
|
+
# Example:
|
69
|
+
# class Person
|
70
|
+
# include Cachetastic::Cacheable
|
71
|
+
#
|
72
|
+
# def always_the_same(x,y)
|
73
|
+
# cacher("always_the_same") do
|
74
|
+
# x + y
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# Person.new.always_the_same(1,2) # => 3
|
80
|
+
# Person.new.always_the_same(2,2) # => 3
|
81
|
+
# Person.new.always_the_same(3,3) # => 3
|
82
|
+
# Person.cacher("always_the_same") # => 3
|
83
|
+
# Person.get_from_cache("always_the_same") # => 3
|
84
|
+
# Cachetastic::Cacheable::PersonCache.get("always_the_same") # => 3
|
85
|
+
#
|
86
|
+
# Person.cacher("say_hi") {"Hi There"} # => "Hi There"
|
87
|
+
# Person.get_from_cache("say_hi") # => "Hi There"
|
88
|
+
# Cachetastic::Cacheable::PersonCache.get("say_hi") # => "Hi There"
|
89
|
+
def cacher(key, expiry = nil)
|
90
|
+
cache_class.get(key) do
|
91
|
+
if block_given?
|
92
|
+
res = yield
|
93
|
+
cache_class.set(key, res, expiry)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Expires the entire cache associated with this objects's cache.
|
99
|
+
#
|
100
|
+
# Example:
|
101
|
+
# class Person
|
102
|
+
# include Cachetastic::Cacheable
|
103
|
+
# attr_accessor :name
|
104
|
+
# def cachetastic_key
|
105
|
+
# self.name
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# Person.set_into_cache(1, "one")
|
110
|
+
# Person.get_from_cache(1) # => "one"
|
111
|
+
# Person.expire_all
|
112
|
+
# Person.get_from_cache(1) # => nil
|
113
|
+
# Person.set_into_cache(1, "one")
|
114
|
+
# Person.get_from_cache(1) # => "one"
|
115
|
+
# Cachetastic::Cacheable::PersonCache.expire_all
|
116
|
+
# Person.get_from_cache(1) # => nil
|
117
|
+
def expire_all
|
118
|
+
cache_class.expire_all
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
# --------------------------
|
124
|
+
# Instance only methods:
|
125
|
+
|
126
|
+
# Unless the object's cachetastic_key method returns nil this method will store
|
127
|
+
# the object in the cache using the object's cachetastic_key as the key.
|
128
|
+
# You *MUST* create an instance level method called cachetastic_key and
|
129
|
+
# have it return a valid key! If you return nil from the cachetastic_key method or you will not be
|
130
|
+
# able to use the cache_self and uncache_self methods.
|
131
|
+
#
|
132
|
+
# Example:
|
133
|
+
# class Person
|
134
|
+
# include Cachetastic::Cacheable
|
135
|
+
# attr_accessor :name
|
136
|
+
# def cachetastic_key
|
137
|
+
# self.name
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# Person.get_from_cache("Mark Bates") # => nil
|
142
|
+
# p = Person.new
|
143
|
+
# p.name = "Mark Bates"
|
144
|
+
# p.cache_self
|
145
|
+
# Person.get_from_cache("Mark Bates") # => "Mark Bates"
|
146
|
+
def cache_self
|
147
|
+
cache_class.set(self.cachetastic_key, self) unless self.cachetastic_key.nil?
|
148
|
+
end
|
149
|
+
|
150
|
+
# Unless the object's cachetastic_key method returns nil this method will delete
|
151
|
+
# the object in the cache using the object's cachetastic_key as the key.
|
152
|
+
# You *MUST* create an instance level method called cachetastic_key and
|
153
|
+
# have it return a valid key! If you return nil from the cachetastic_key method or you will not be
|
154
|
+
# able to use the cache_self and uncache_self methods.
|
155
|
+
#
|
156
|
+
# Example:
|
157
|
+
# class Person
|
158
|
+
# include Cachetastic::Cacheable
|
159
|
+
# attr_accessor :name
|
160
|
+
# def cachetastic_key
|
161
|
+
# self.name
|
162
|
+
# end
|
163
|
+
# end
|
164
|
+
#
|
165
|
+
# Person.get_from_cache("Mark Bates") # => nil
|
166
|
+
# p = Person.new
|
167
|
+
# p.name = "Mark Bates"
|
168
|
+
# p.cache_self
|
169
|
+
# Person.get_from_cache("Mark Bates") # => "Mark Bates"
|
170
|
+
# p.uncache_self
|
171
|
+
# Person.get_from_cache("Mark Bates") # => nil
|
172
|
+
def uncache_self
|
173
|
+
cache_class.delete(self.cachetastic_key) unless self.cachetastic_key.nil?
|
174
|
+
end
|
175
|
+
|
176
|
+
# --------------------------
|
177
|
+
|
178
|
+
def self.included(klass) # :nodoc:
|
179
|
+
klass.send(:include, ClassAndInstanceMethods)
|
180
|
+
klass.extend(ClassOnlyMethods)
|
181
|
+
klass.extend(ClassAndInstanceMethods)
|
182
|
+
end
|
183
|
+
|
184
|
+
module ClassOnlyMethods
|
185
|
+
# Returns an object from the cache for a given key.
|
186
|
+
def get_from_cache(key, &block)
|
187
|
+
cache_class.get(key, &block)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Deletes an object from the cache for a given key.
|
191
|
+
def delete_from_cache(key)
|
192
|
+
cache_class.delete(key)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Sets an object into the cache for a given key.
|
196
|
+
def set_into_cache(key, value, expiry = 0)
|
197
|
+
cache_class.set(key, value, expiry)
|
198
|
+
end
|
199
|
+
end # ClassMethods
|
200
|
+
|
201
|
+
end # Cacheable
|
202
|
+
end # Cachetastic
|