method_cacher 0.0.1
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/.gitignore +17 -0
- data/.rspec +1 -0
- data/.rvmrc +71 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +50 -0
- data/LICENSE +19 -0
- data/README.md +85 -0
- data/Rakefile +7 -0
- data/lib/method_cacher.rb +4 -0
- data/lib/method_cacher/base.rb +159 -0
- data/lib/method_cacher/railtie.rb +10 -0
- data/lib/method_cacher/version.rb +3 -0
- data/method_cacher.gemspec +23 -0
- data/spec/method_cacher/base_spec.rb +276 -0
- data/spec/method_cacher/base_test_helper.rb +264 -0
- data/spec/method_cacher_spec.rb +0 -0
- data/spec/rspec_matchers.rb +14 -0
- data/spec/spec_helper.rb +4 -0
- metadata +113 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.rvmrc
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
+
# development environment upon cd'ing into the directory
|
5
|
+
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
|
7
|
+
environment_id="ruby-1.9.2-p180@method_cacher"
|
8
|
+
|
9
|
+
#
|
10
|
+
# Uncomment following line if you want options to be set only for given project.
|
11
|
+
#
|
12
|
+
# PROJECT_JRUBY_OPTS=( --1.9 )
|
13
|
+
#
|
14
|
+
# The variable PROJECT_JRUBY_OPTS requires the following to be run in shell:
|
15
|
+
#
|
16
|
+
# chmod +x ${rvm_path}/hooks/after_use_jruby_opts
|
17
|
+
#
|
18
|
+
|
19
|
+
#
|
20
|
+
# First we attempt to load the desired environment directly from the environment
|
21
|
+
# file. This is very fast and efficient compared to running through the entire
|
22
|
+
# CLI and selector. If you want feedback on which environment was used then
|
23
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
24
|
+
#
|
25
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
|
26
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
27
|
+
then
|
28
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
29
|
+
|
30
|
+
if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
|
31
|
+
then
|
32
|
+
. "${rvm_path:-$HOME/.rvm}/hooks/after_use"
|
33
|
+
fi
|
34
|
+
else
|
35
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
36
|
+
if ! rvm --create use "$environment_id"
|
37
|
+
then
|
38
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
39
|
+
return 1
|
40
|
+
fi
|
41
|
+
fi
|
42
|
+
|
43
|
+
#
|
44
|
+
# If you use an RVM gemset file to install a list of gems (*.gems), you can have
|
45
|
+
# it be automatically loaded. Uncomment the following and adjust the filename if
|
46
|
+
# necessary.
|
47
|
+
#
|
48
|
+
# filename=".gems"
|
49
|
+
# if [[ -s "$filename" ]]
|
50
|
+
# then
|
51
|
+
# rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
|
52
|
+
# fi
|
53
|
+
|
54
|
+
# If you use bundler, this might be useful to you:
|
55
|
+
# if [[ -s Gemfile ]] && ! command -v bundle >/dev/null
|
56
|
+
# then
|
57
|
+
# printf "The rubygem 'bundler' is not installed. Installing it now.\n"
|
58
|
+
# gem install bundler
|
59
|
+
# fi
|
60
|
+
# if [[ -s Gemfile ]] && command -v bundle
|
61
|
+
# then
|
62
|
+
# bundle install
|
63
|
+
# fi
|
64
|
+
|
65
|
+
if [[ $- == *i* ]] # check for interactive shells
|
66
|
+
then
|
67
|
+
echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
|
68
|
+
else
|
69
|
+
echo "Using: $GEM_HOME" # don't use colors in interactive shells
|
70
|
+
fi
|
71
|
+
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
method_cacher (0.0.1.alpha)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activemodel (3.0.11)
|
10
|
+
activesupport (= 3.0.11)
|
11
|
+
builder (~> 2.1.2)
|
12
|
+
i18n (~> 0.5.0)
|
13
|
+
activesupport (3.0.11)
|
14
|
+
archive-tar-minitar (0.5.2)
|
15
|
+
builder (2.1.2)
|
16
|
+
columnize (0.3.6)
|
17
|
+
diff-lcs (1.1.3)
|
18
|
+
i18n (0.5.0)
|
19
|
+
linecache19 (0.5.12)
|
20
|
+
ruby_core_source (>= 0.1.4)
|
21
|
+
rspec (2.7.0)
|
22
|
+
rspec-core (~> 2.7.0)
|
23
|
+
rspec-expectations (~> 2.7.0)
|
24
|
+
rspec-mocks (~> 2.7.0)
|
25
|
+
rspec-core (2.7.1)
|
26
|
+
rspec-expectations (2.7.0)
|
27
|
+
diff-lcs (~> 1.1.2)
|
28
|
+
rspec-mocks (2.7.0)
|
29
|
+
ruby-debug-base19 (0.11.25)
|
30
|
+
columnize (>= 0.3.1)
|
31
|
+
linecache19 (>= 0.5.11)
|
32
|
+
ruby_core_source (>= 0.1.4)
|
33
|
+
ruby-debug19 (0.11.6)
|
34
|
+
columnize (>= 0.3.1)
|
35
|
+
linecache19 (>= 0.5.11)
|
36
|
+
ruby-debug-base19 (>= 0.11.19)
|
37
|
+
ruby_core_source (0.1.5)
|
38
|
+
archive-tar-minitar (>= 0.5.2)
|
39
|
+
supermodel (0.1.6)
|
40
|
+
activemodel (~> 3.0.0)
|
41
|
+
|
42
|
+
PLATFORMS
|
43
|
+
ruby
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
activesupport
|
47
|
+
method_cacher!
|
48
|
+
rspec
|
49
|
+
ruby-debug19
|
50
|
+
supermodel
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) 2011 Yaron Walfish
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
8
|
+
so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Method Cacher
|
2
|
+
|
3
|
+
Wraps specified methods with a mechanism that caches the return values.
|
4
|
+
|
5
|
+
__Features:__
|
6
|
+
|
7
|
+
+ Can cache both instance and singleton (i.e. class) methods.
|
8
|
+
+ Differentiates among calls to a method with different arguments.
|
9
|
+
+ Generates methods to provide access the original uncached methods.
|
10
|
+
+ Generates methods to clear the cache of each cached method.
|
11
|
+
+ To specify methods to be cached, just call `caches_method :foo, :bar ...` before or after the actual definition of `foo` and `bar`.
|
12
|
+
+ When used with Rails, it automatically uses the cache store configured in Rails.
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add the `method_cacher` gem your Gemfile and run the `bundle` command to install it.
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'method_cacher'
|
20
|
+
```
|
21
|
+
|
22
|
+
__Requires Ruby 1.9.2 or later.__
|
23
|
+
|
24
|
+
## Configuration
|
25
|
+
|
26
|
+
...
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Include the method cacher module in the class whose methods you wish to cache.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
include MethodCacher::Base
|
34
|
+
```
|
35
|
+
|
36
|
+
The module is included automatically for ActiveRecord when used in Rails.
|
37
|
+
|
38
|
+
Call `cache_method` from within the class definition, listing the names of the methods that are to be cached.
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
cache_method :instance_foo, :instance_bar, singleton: [:singleton_foo, :singleton_bar], obj_key: proc { |obj| obj.obj_key }
|
42
|
+
```
|
43
|
+
|
44
|
+
Instance methods are specified as symbol arguments.
|
45
|
+
|
46
|
+
__Options:__
|
47
|
+
|
48
|
+
+ :singleton - Singleton methods to be cached are specified in an array of symbols passed through this option.
|
49
|
+
+ :obj\_key - A _proc_ that accepts the cached object as a single parameter. This _proc_ should return a value identifying this object.
|
50
|
+
If this option is not specified, the object key defaults to the value returned by a method named _id_, which is convenient for usage
|
51
|
+
with ActiveRecord objects.
|
52
|
+
|
53
|
+
`cache_method` can take any number of instance or singleton methods at once.
|
54
|
+
|
55
|
+
Subsequent calls to `cache_method` are possible in order to specify additional methods to be cached.
|
56
|
+
Specifying :obj\_id multiple times results in the last one being used for the class.
|
57
|
+
|
58
|
+
`cache_method` can be called _before_ or _after_ the specified methods are defined.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
cache_method :foo # this works
|
62
|
+
def foo
|
63
|
+
...
|
64
|
+
end
|
65
|
+
|
66
|
+
def bar
|
67
|
+
...
|
68
|
+
end
|
69
|
+
cache_method :bar # this also works
|
70
|
+
```
|
71
|
+
|
72
|
+
`cache_method` replaces each specified method with a cached version.
|
73
|
+
|
74
|
+
The cached versions take the same arguments as the originals, with different arguments caching separately.
|
75
|
+
|
76
|
+
Each of the original methods is made accessible through the alias `uncached_` followed by the method's name.
|
77
|
+
E.g. if the method is `foo`, the original is aliased as `uncached_foo`.
|
78
|
+
|
79
|
+
`cache_method` also adds methods to clear the cache of each cached method.
|
80
|
+
These methods are named `clear_cache_for_` followed by the cached method's name.
|
81
|
+
The clear cache methods take identical arguments as their respective original and cached methods, and only
|
82
|
+
clear the cache for the given set of arguments.
|
83
|
+
|
84
|
+
So for example, issuing `clear_cache_for_foo('a')`, would clear the cache for a call to `foo('a')`
|
85
|
+
but not to `foo('b')`.
|
data/Rakefile
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module MethodCacher
|
6
|
+
# An object that holds configuration vars for MethodCacher
|
7
|
+
class Configuration
|
8
|
+
def caching_strategy= strategy
|
9
|
+
@caching_strategy = strategy
|
10
|
+
end
|
11
|
+
|
12
|
+
def caching_strategy
|
13
|
+
if @caching_strategy
|
14
|
+
@caching_strategy
|
15
|
+
elsif defined? Rails
|
16
|
+
Rails.cache # default to the rails caching strategy if it's a Rails app
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@@config = MethodCacher::Configuration.new
|
22
|
+
mattr_reader :config
|
23
|
+
|
24
|
+
# Gives a block configuration style like that of Rails.
|
25
|
+
def self.configure(&block)
|
26
|
+
if block_given?
|
27
|
+
if block.arity == 1
|
28
|
+
# allows this style config: MethodCacher.configure do |config| config.variable = ... end
|
29
|
+
yield config
|
30
|
+
else
|
31
|
+
# allows this style config: MethodCacher.configure do config.variable = ... end
|
32
|
+
# While this option is more elegant because it doesn't require a block variable, it loses access to
|
33
|
+
# methods defined in the calling context because the context switches to that of the self object.
|
34
|
+
instance_eval &block
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module Base
|
40
|
+
extend ActiveSupport::Concern
|
41
|
+
|
42
|
+
# default object key proc
|
43
|
+
OBJECT_KEY_PROC_DEFAULT = lambda { |obj| obj.id }
|
44
|
+
|
45
|
+
module ClassMethods
|
46
|
+
|
47
|
+
attr_accessor :methods_to_be_cached, :cached_methods, :obj_key
|
48
|
+
attr_accessor :singleton_methods_to_be_cached, :singleton_cached_methods
|
49
|
+
|
50
|
+
def caches_method(*method_names)
|
51
|
+
initialize_variables
|
52
|
+
|
53
|
+
# process parameters
|
54
|
+
options = method_names.extract_options!
|
55
|
+
|
56
|
+
self.obj_key = options[:obj_key] || self.obj_key # if obj_key is given in the option, replace it with what's given
|
57
|
+
self.methods_to_be_cached += method_names
|
58
|
+
self.singleton_methods_to_be_cached += [options[:singleton]].flatten
|
59
|
+
|
60
|
+
# Cache all currently defined instance methods that are given in the parameters.
|
61
|
+
self.methods_to_be_cached.clone.each do |method_name|
|
62
|
+
add_cached_method(method_name) if (private_instance_methods + protected_instance_methods + public_instance_methods).include?(method_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Cache all currently defined singleton methods given in the parameters.
|
66
|
+
self.singleton_methods_to_be_cached.clone.each do |method_name|
|
67
|
+
singleton_add_cached_method(method_name) if singleton_methods.include?(method_name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# This callback adds caching to the methods that were not defined yet when caches_method was called.
|
72
|
+
def method_added(method_name)
|
73
|
+
super
|
74
|
+
initialize_variables
|
75
|
+
add_cached_method(method_name) if self.methods_to_be_cached.include?(method_name) #and public_instance_methods.include?(method_name) # commented section is for testing the related spec
|
76
|
+
end
|
77
|
+
|
78
|
+
# Same as method_added but for singleton methods.
|
79
|
+
def singleton_method_added(method_name)
|
80
|
+
super
|
81
|
+
initialize_variables
|
82
|
+
singleton_add_cached_method(method_name) if self.singleton_methods_to_be_cached.include?(method_name)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
# Initialize class instance variables for instance method caching.
|
88
|
+
def initialize_variables
|
89
|
+
self.obj_key ||= OBJECT_KEY_PROC_DEFAULT # identifies the object of this class, defaults to the object's id if defined
|
90
|
+
|
91
|
+
self.methods_to_be_cached ||= Set.new # stores the names of the methods designated to be cached
|
92
|
+
self.cached_methods ||= Set.new # stores the methods that are cached
|
93
|
+
|
94
|
+
# initialize class instance variables for singleton method caching
|
95
|
+
self.singleton_methods_to_be_cached ||= Set.new # stores the names of the methods designated to be cached
|
96
|
+
self.singleton_cached_methods ||= Set.new # stores the methods that are cached
|
97
|
+
end
|
98
|
+
|
99
|
+
# Creates the key used to cache a singleton method of the object.
|
100
|
+
def singleton_cached_method_key(method_name, *args)
|
101
|
+
[self.name, method_name, *args]
|
102
|
+
end
|
103
|
+
|
104
|
+
# Adds code to the class to cache the given instance method.
|
105
|
+
def add_cached_method(method_name)
|
106
|
+
self.methods_to_be_cached.delete(method_name)
|
107
|
+
self.cached_methods <<= method_name
|
108
|
+
|
109
|
+
# TODO: Make cached methods have the same accessibility (i.e. public/private/protected) as the original method.
|
110
|
+
class_eval <<-END_EVAL, __FILE__, __LINE__ + 1
|
111
|
+
alias :uncached_#{method_name} :#{method_name}
|
112
|
+
def #{method_name}(*args)
|
113
|
+
key = cached_method_key(:#{method_name}, *args)
|
114
|
+
key.nil? ? uncached_#{method_name}(*args) : MethodCacher.config.caching_strategy.fetch(key) { uncached_#{method_name}(*args) } # cache only for non-nil keys
|
115
|
+
end
|
116
|
+
|
117
|
+
def clear_cache_for_#{method_name}(*args)
|
118
|
+
MethodCacher.config.caching_strategy.delete(cached_method_key(:#{method_name}, *args))
|
119
|
+
end
|
120
|
+
END_EVAL
|
121
|
+
end
|
122
|
+
|
123
|
+
# Adds code to the class to cache the given singleton method.
|
124
|
+
def singleton_add_cached_method(method_name)
|
125
|
+
self.singleton_methods_to_be_cached.delete(method_name)
|
126
|
+
self.singleton_cached_methods <<= method_name
|
127
|
+
class_eval <<-END_EVAL, __FILE__, __LINE__ + 1
|
128
|
+
class <<self
|
129
|
+
alias :uncached_#{method_name} :#{method_name}
|
130
|
+
def #{method_name}(*args)
|
131
|
+
MethodCacher.config.caching_strategy.fetch(singleton_cached_method_key(:#{method_name}, *args)) { uncached_#{method_name}(*args) }
|
132
|
+
end
|
133
|
+
|
134
|
+
def clear_cache_for_#{method_name}(*args)
|
135
|
+
MethodCacher.config.caching_strategy.delete(singleton_cached_method_key(:#{method_name}, *args))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
END_EVAL
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
module InstanceMethods
|
144
|
+
|
145
|
+
# A helper that clears the cache for all the cached methods of this object that are argument-less.
|
146
|
+
def clear_method_cache
|
147
|
+
self.class.cached_methods.each { |method_name| MethodCacher.config.caching_strategy.delete(cached_method_key(method_name)) }
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
# Creates the key used to cache a method of the object.
|
153
|
+
def cached_method_key(method_name, *args)
|
154
|
+
obj_key = self.class.obj_key.call(self)
|
155
|
+
[self.class.name, obj_key, method_name, *args]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__) # $: is the load path
|
3
|
+
require 'method_cacher/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.authors = ["Yaron Walfish"]
|
7
|
+
gem.email = ["yaronw@yaronw.com"]
|
8
|
+
gem.description = %q{Caches Instance and Singleton Methods}
|
9
|
+
gem.summary = %q{Wraps specified instance and singleton methods with the Rails caching mechanism.}
|
10
|
+
gem.homepage = ""
|
11
|
+
|
12
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
13
|
+
gem.files = `git ls-files`.split("\n")
|
14
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
gem.name = "method_cacher"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = MethodCacher::VERSION
|
18
|
+
|
19
|
+
gem.add_development_dependency 'rspec'
|
20
|
+
gem.add_development_dependency 'supermodel'
|
21
|
+
gem.add_development_dependency 'activesupport'
|
22
|
+
gem.add_development_dependency 'ruby-debug19'
|
23
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/cache'
|
3
|
+
require 'method_cacher/base_test_helper'
|
4
|
+
|
5
|
+
describe MethodCacher::Configuration do
|
6
|
+
describe "yield style configuration" do
|
7
|
+
it "should assign configuration variables" do
|
8
|
+
MethodCacher.configure do |c|
|
9
|
+
c.caching_strategy = "test1"
|
10
|
+
end
|
11
|
+
|
12
|
+
MethodCacher.config.caching_strategy.should == "test1"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "eval style configuration" do
|
17
|
+
it "should assign configuration variables" do
|
18
|
+
MethodCacher.configure do
|
19
|
+
config.caching_strategy = "test2"
|
20
|
+
end
|
21
|
+
|
22
|
+
MethodCacher.config.caching_strategy.should == "test2"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe MethodCacher::Base do
|
28
|
+
before (:all) do
|
29
|
+
MethodCacher.configure do
|
30
|
+
config.caching_strategy = ActiveSupport::Cache.lookup_store(:memory_store)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#caches_method" do
|
35
|
+
context "when specified BEFORE the declaration of the methods to be cached" do
|
36
|
+
it "should cache the INSTANCE method associated with the names given in the arguments" do
|
37
|
+
obj = FirstClass.new
|
38
|
+
[:foo1, :foo2].each do |name|
|
39
|
+
lambda { obj.send(name) }.should be_twice_the_same # verify that original function is not called twice
|
40
|
+
obj.send(name).should == Dummy.current_value # verify that the right value is actually cached
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not cache INSTANCE methods whose names are not given in the arguments" do
|
45
|
+
obj = FirstClass.new
|
46
|
+
lambda { obj.foo3 }.should_not be_twice_the_same
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should cache the SINGLETON methods associated with the names given in the :singleton option array" do
|
50
|
+
[:bar1, :bar2].each do |name|
|
51
|
+
lambda { FirstClass.send(name) }.should be_twice_the_same
|
52
|
+
FirstClass.send(name).should == Dummy.current_value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should not cache SINGLETON methods whose names are not given in the :singleton option" do
|
57
|
+
lambda { FirstClass.bar3 }.should_not be_twice_the_same
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should cache INSTANCE methods given in separate calls" do
|
61
|
+
(1..4).to_a.collect { |x| :"foo#{x}" }.each do |name|
|
62
|
+
obj = SeventhClass.new
|
63
|
+
lambda { obj.send(name) }.should be_twice_the_same
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should cache SINGLETON methods given in separate calls" do
|
68
|
+
(1..4).to_a.collect { |x| :"bar#{x}" }.each do |name|
|
69
|
+
lambda { SeventhClass.send(name) }.should be_twice_the_same
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should cache protected INSTANCE methods" do
|
74
|
+
obj = EighthClass.new
|
75
|
+
debugger
|
76
|
+
lambda { obj.send(:foo1) }.should be_twice_the_same
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should cache private INSTANCE methods" do
|
80
|
+
obj = EighthClass.new
|
81
|
+
lambda { obj.send(:foo3) }.should be_twice_the_same
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when specified AFTER the declaration of the methods to be cached" do
|
86
|
+
it "should cache the INSTANCE method associated with the names given in the arguments" do
|
87
|
+
obj = SecondClass.new
|
88
|
+
[:foo1, :foo2].each do |name|
|
89
|
+
lambda { obj.send(name) }.should be_twice_the_same
|
90
|
+
obj.send(name).should == Dummy.current_value
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not cache INSTANCE methods whose names are not given in the arguments" do
|
95
|
+
obj = SecondClass.new
|
96
|
+
lambda { obj.foo3 }.should_not be_twice_the_same
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should cache the SINGLETON methods associated with the names given in the :singleton option array" do
|
100
|
+
[:bar1, :bar2].each do |name|
|
101
|
+
lambda { SecondClass.send(name) }.should be_twice_the_same
|
102
|
+
SecondClass.send(name).should == Dummy.current_value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should not cache SINGLETON methods whose names are not given in the :singleton option" do
|
107
|
+
lambda { SecondClass.bar3 }.should_not be_twice_the_same
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should cache INSTANCE methods given in separate calls" do
|
111
|
+
(5..8).to_a.collect { |x| :"foo#{x}" }.each do |name|
|
112
|
+
obj = SeventhClass.new
|
113
|
+
lambda { obj.send(name) }.should be_twice_the_same
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should cache SINGLETON methods given in separate calls" do
|
118
|
+
(5..8).to_a.collect { |x| :"bar#{x}" }.each do |name|
|
119
|
+
lambda { SeventhClass.send(name) }.should be_twice_the_same
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should cache protected INSTANCE methods" do
|
124
|
+
obj = EighthClass.new
|
125
|
+
lambda { obj.send(:foo2) }.should be_twice_the_same
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should cache private INSTANCE methods" do
|
129
|
+
obj = EighthClass.new
|
130
|
+
lambda { obj.send(:foo4) }.should be_twice_the_same
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "cache key mechanism for INSTANCE methods" do
|
135
|
+
context "when caching an INSTANCE method of one object" do
|
136
|
+
it "should have different sets of arguments cache separately" do
|
137
|
+
obj = FirstClass.new
|
138
|
+
lambda { obj.foo1(1,2) }.should be_twice_the_same
|
139
|
+
lambda { obj.foo1(1,3) }.should be_twice_the_same
|
140
|
+
obj.foo1(1,3).should_not == obj.foo1(1,2)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "when caching the same INSTANCE method with identical parameter sets and of the same class" do
|
145
|
+
it "should have objects whose :obj_key proc evaluates differently cache separately" do
|
146
|
+
obj1 = ThirdClass.new
|
147
|
+
obj1.obj_key = 1
|
148
|
+
obj2 = ThirdClass.new
|
149
|
+
obj2.obj_key = 2
|
150
|
+
|
151
|
+
obj1.foo # cache methods
|
152
|
+
obj2.foo
|
153
|
+
|
154
|
+
obj2.foo.should_not == obj1.foo
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should have objects whose :obj_key proc evaluates the same cache one value" do
|
158
|
+
obj1 = ThirdClass.new
|
159
|
+
obj1.obj_key = 1
|
160
|
+
obj2 = ThirdClass.new
|
161
|
+
obj2.obj_key = 1
|
162
|
+
|
163
|
+
obj1.foo # cache methods
|
164
|
+
obj2.foo
|
165
|
+
|
166
|
+
obj2.foo.should == obj1.foo
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "when caching INSTANCE methods of identical names with identical parameter sets, and identical :obj_key proc values" do
|
171
|
+
it "should have different classes cache separately" do
|
172
|
+
obj1 = ThirdClass.new
|
173
|
+
obj1.obj_key = 1
|
174
|
+
obj2 = FourthClass.new
|
175
|
+
obj2.obj_key = 1
|
176
|
+
|
177
|
+
obj1.foo # cache methods
|
178
|
+
obj2.foo
|
179
|
+
|
180
|
+
obj2.foo.should_not == obj1.foo
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should default the :obj_key option to the instance method named 'id'" do
|
185
|
+
# test that the :obj_key mechanism is working for the default 'id' class
|
186
|
+
obj1 = FifthClass.new
|
187
|
+
obj1.id = 1
|
188
|
+
obj2 = FifthClass.new
|
189
|
+
obj2.id = 2
|
190
|
+
|
191
|
+
obj1.foo # cache methods
|
192
|
+
obj2.foo
|
193
|
+
|
194
|
+
obj2.foo.should_not == obj1.foo
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should raise an exception if neither an :obj_key option is given nor the default fallback :id method is defined" do
|
198
|
+
obj = SixthClass.new
|
199
|
+
lambda { obj.foo }.should raise_error(NoMethodError)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "cache key mechanism for SINGLETON methods" do
|
204
|
+
context "when caching a SINGLETON method of one class" do
|
205
|
+
it "should have different sets of arguments cache separately" do
|
206
|
+
lambda { FirstClass.bar1(1,2) }.should be_twice_the_same
|
207
|
+
lambda { FirstClass.bar1(1,3) }.should be_twice_the_same
|
208
|
+
FirstClass.bar1(1,3).should_not == FirstClass.bar1(1,2)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context "when caching SINGLETON methods of identical names with identical parameter sets" do
|
213
|
+
it "should have different classes cache separately" do
|
214
|
+
ThirdClass.bar # cache methods
|
215
|
+
FourthClass.bar
|
216
|
+
|
217
|
+
FourthClass.bar.should_not == ThirdClass.bar
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe "dynamic methods creation" do
|
223
|
+
context "when caching an INSTANCE method" do
|
224
|
+
it "should include a method named uncached_[name of original method] that calls the original uncached method" do
|
225
|
+
obj = FirstClass.new
|
226
|
+
|
227
|
+
# works for methods without arguments
|
228
|
+
lambda { obj.uncached_foo1 }.should_not be_twice_the_same # uncached function should not cache # for testing this assertion: def uncached_#{method_name} \n rand 1000000000 \n end
|
229
|
+
obj.uncached_foo1.should == Dummy.current_value # uncached function should call original method # for testing this assertion: def uncached_#{method_name} \n 1 \n end
|
230
|
+
|
231
|
+
# works for methods with arguments
|
232
|
+
lambda { obj.uncached_foo1(1,2) }.should_not be_twice_the_same # uncached function should not cache
|
233
|
+
obj.uncached_foo1(1,2).should == Dummy.current_value(1,2) # uncached function should call original method
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should include a method named clear_cache_for_[name of original method] that clears the cache for a specific method with specific arguments" do
|
237
|
+
obj = FirstClass.new
|
238
|
+
|
239
|
+
# works for methods without arguments
|
240
|
+
val = obj.foo1
|
241
|
+
obj.clear_cache_for_foo1
|
242
|
+
obj.foo1.should_not == val
|
243
|
+
|
244
|
+
# works for methods with arguments
|
245
|
+
val = obj.foo1(1,2)
|
246
|
+
obj.clear_cache_for_foo1(1,2)
|
247
|
+
obj.foo1(1,2).should_not == val
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context "when caching a SINGLETON method" do
|
252
|
+
it "should include a method that calls the original uncached method" do
|
253
|
+
# works for methods without arguments
|
254
|
+
lambda { FirstClass.uncached_bar1 }.should_not be_twice_the_same # should not cache
|
255
|
+
FirstClass.uncached_bar1.should == Dummy.current_value # uncached function should call original method
|
256
|
+
|
257
|
+
# works for methods with arguments
|
258
|
+
lambda { FirstClass.uncached_bar1(1,2) }.should_not be_twice_the_same # should not cache
|
259
|
+
FirstClass.uncached_bar1(1,2).should == Dummy.current_value(1,2) # uncached function should call original method
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should include a method named clear_cache_for_[name of original method] that clears the cache for a specific method with specific arguments" do
|
263
|
+
# works for methods without arguments
|
264
|
+
val = FirstClass.bar1
|
265
|
+
FirstClass.clear_cache_for_bar1
|
266
|
+
FirstClass.bar1.should_not == val
|
267
|
+
|
268
|
+
# works for methods with arguments
|
269
|
+
val = FirstClass.bar1(1,2)
|
270
|
+
FirstClass.clear_cache_for_bar1(1,2)
|
271
|
+
FirstClass.bar1(1,2).should_not == val
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
@@ -0,0 +1,264 @@
|
|
1
|
+
# Provides a function that returns a different value with each call and also bases the return value on the arguments given.
|
2
|
+
module Dummy
|
3
|
+
@@counter = 0
|
4
|
+
def self.function(*args)
|
5
|
+
@@counter += 1
|
6
|
+
current_value(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
# returns the current value of function without changin it
|
10
|
+
def self.current_value(*args)
|
11
|
+
"#{@@counter} #{args}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# for testing method caching when caches_method is called before the methods are defined
|
16
|
+
class FirstClass
|
17
|
+
include MethodCacher::Base
|
18
|
+
|
19
|
+
def id
|
20
|
+
object_id
|
21
|
+
end
|
22
|
+
|
23
|
+
caches_method :foo1, :foo2, singleton: [:bar1, :bar2] #, :obj_key => proc { |s| s.object_id }
|
24
|
+
# test instance methods.
|
25
|
+
def foo1(*args)
|
26
|
+
Dummy.function(*args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def foo2(*args)
|
30
|
+
Dummy.function(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def foo3(*args)
|
34
|
+
Dummy.function(*args)
|
35
|
+
end
|
36
|
+
|
37
|
+
class <<self
|
38
|
+
# test singleton (i.e. class) methods.
|
39
|
+
def bar1(*args)
|
40
|
+
Dummy.function(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
def bar2(*args)
|
44
|
+
Dummy.function(*args)
|
45
|
+
end
|
46
|
+
|
47
|
+
def bar3(*args)
|
48
|
+
Dummy.function(*args)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# for testing method caching when caches_method is called after the methods are defined
|
54
|
+
class SecondClass
|
55
|
+
include MethodCacher::Base
|
56
|
+
|
57
|
+
def id
|
58
|
+
object_id
|
59
|
+
end
|
60
|
+
|
61
|
+
# test instance methods.
|
62
|
+
def foo1
|
63
|
+
Dummy.function
|
64
|
+
end
|
65
|
+
|
66
|
+
def foo2
|
67
|
+
Dummy.function
|
68
|
+
end
|
69
|
+
|
70
|
+
def foo3
|
71
|
+
Dummy.function
|
72
|
+
end
|
73
|
+
|
74
|
+
class <<self
|
75
|
+
# test singleton (i.e. class) methods.
|
76
|
+
def bar1
|
77
|
+
Dummy.function
|
78
|
+
end
|
79
|
+
|
80
|
+
def bar2
|
81
|
+
Dummy.function
|
82
|
+
end
|
83
|
+
|
84
|
+
def bar3
|
85
|
+
Dummy.function
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
caches_method :foo1, :foo2, singleton: [:bar1, :bar2]
|
90
|
+
end
|
91
|
+
|
92
|
+
# for testing :obj_key option and cache differentiation
|
93
|
+
class ThirdClass
|
94
|
+
include MethodCacher::Base
|
95
|
+
|
96
|
+
attr_accessor :obj_key
|
97
|
+
|
98
|
+
caches_method :foo, singleton: :bar, obj_key: proc { |obj| obj.obj_key }
|
99
|
+
|
100
|
+
def foo
|
101
|
+
Dummy.function
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.bar
|
105
|
+
Dummy.function
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# same as previous class
|
110
|
+
class FourthClass
|
111
|
+
include MethodCacher::Base
|
112
|
+
|
113
|
+
attr_accessor :obj_key
|
114
|
+
|
115
|
+
caches_method :foo, singleton: :bar, obj_key: proc { |obj| obj.obj_key }
|
116
|
+
|
117
|
+
def foo
|
118
|
+
Dummy.function
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.bar
|
122
|
+
Dummy.function
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# for testing :obj_key option default
|
127
|
+
class FifthClass
|
128
|
+
include MethodCacher::Base
|
129
|
+
|
130
|
+
attr_accessor :id
|
131
|
+
|
132
|
+
caches_method :foo
|
133
|
+
|
134
|
+
def foo
|
135
|
+
Dummy.function
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# for testing when the :obj_key option is undefined and the default id method is missing
|
140
|
+
class SixthClass
|
141
|
+
include MethodCacher::Base
|
142
|
+
|
143
|
+
caches_method :foo
|
144
|
+
|
145
|
+
def foo
|
146
|
+
Dummy.function
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# for testing adding methods to be cached using separate caches_method calls
|
151
|
+
class SeventhClass
|
152
|
+
include MethodCacher::Base
|
153
|
+
|
154
|
+
def id
|
155
|
+
object_id
|
156
|
+
end
|
157
|
+
|
158
|
+
caches_method :foo1, singleton: :bar1
|
159
|
+
caches_method :foo2, singleton: :bar2
|
160
|
+
caches_method :foo3, :foo4, singleton: [:bar3, :bar4]
|
161
|
+
|
162
|
+
# test instance methods.
|
163
|
+
def foo1
|
164
|
+
Dummy.function
|
165
|
+
end
|
166
|
+
|
167
|
+
def foo2
|
168
|
+
Dummy.function
|
169
|
+
end
|
170
|
+
|
171
|
+
def foo3
|
172
|
+
Dummy.function
|
173
|
+
end
|
174
|
+
|
175
|
+
def foo4
|
176
|
+
Dummy.function
|
177
|
+
end
|
178
|
+
|
179
|
+
def foo5
|
180
|
+
Dummy.function
|
181
|
+
end
|
182
|
+
|
183
|
+
def foo6
|
184
|
+
Dummy.function
|
185
|
+
end
|
186
|
+
|
187
|
+
def foo7
|
188
|
+
Dummy.function
|
189
|
+
end
|
190
|
+
|
191
|
+
def foo8
|
192
|
+
Dummy.function
|
193
|
+
end
|
194
|
+
|
195
|
+
class <<self
|
196
|
+
# test singleton (i.e. class) methods.
|
197
|
+
def bar1
|
198
|
+
Dummy.function
|
199
|
+
end
|
200
|
+
|
201
|
+
def bar2
|
202
|
+
Dummy.function
|
203
|
+
end
|
204
|
+
|
205
|
+
def bar3
|
206
|
+
Dummy.function
|
207
|
+
end
|
208
|
+
|
209
|
+
def bar4
|
210
|
+
Dummy.function
|
211
|
+
end
|
212
|
+
|
213
|
+
def bar5
|
214
|
+
Dummy.function
|
215
|
+
end
|
216
|
+
|
217
|
+
def bar6
|
218
|
+
Dummy.function
|
219
|
+
end
|
220
|
+
|
221
|
+
def bar7
|
222
|
+
Dummy.function
|
223
|
+
end
|
224
|
+
|
225
|
+
def bar8
|
226
|
+
Dummy.function
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
caches_method :foo5, singleton: :bar5
|
231
|
+
caches_method :foo6, singleton: :bar6
|
232
|
+
caches_method :foo7, :foo8, singleton: [:bar7, :bar8]
|
233
|
+
end
|
234
|
+
|
235
|
+
# for testing caching of private and protected instance methods
|
236
|
+
class EighthClass
|
237
|
+
include MethodCacher::Base
|
238
|
+
|
239
|
+
def id
|
240
|
+
object_id
|
241
|
+
end
|
242
|
+
|
243
|
+
caches_method :foo1, :foo3
|
244
|
+
|
245
|
+
protected
|
246
|
+
def foo1
|
247
|
+
Dummy.function
|
248
|
+
end
|
249
|
+
|
250
|
+
def foo2
|
251
|
+
Dummy.function
|
252
|
+
end
|
253
|
+
|
254
|
+
private
|
255
|
+
def foo3
|
256
|
+
Dummy.function
|
257
|
+
end
|
258
|
+
|
259
|
+
def foo4
|
260
|
+
Dummy.function
|
261
|
+
end
|
262
|
+
|
263
|
+
#caches_method :foo2, :foo4
|
264
|
+
end
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
RSpec::Matchers.define :be_twice_the_same do |options|
|
2
|
+
match do |proc|
|
3
|
+
cached = proc.call
|
4
|
+
proc.call == cached
|
5
|
+
end
|
6
|
+
|
7
|
+
failure_message_for_should do |proc|
|
8
|
+
"expected #{proc} to return the same value when called twice"
|
9
|
+
end
|
10
|
+
|
11
|
+
failure_message_for_should_not do |proc|
|
12
|
+
"expected #{proc} to return two different values when called twice"
|
13
|
+
end
|
14
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: method_cacher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Yaron Walfish
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &2156410720 !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: *2156410720
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: supermodel
|
27
|
+
requirement: &2156410000 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2156410000
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: activesupport
|
38
|
+
requirement: &2156408920 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2156408920
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: ruby-debug19
|
49
|
+
requirement: &2156408100 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2156408100
|
58
|
+
description: Caches Instance and Singleton Methods
|
59
|
+
email:
|
60
|
+
- yaronw@yaronw.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- .gitignore
|
66
|
+
- .rspec
|
67
|
+
- .rvmrc
|
68
|
+
- CHANGELOG.md
|
69
|
+
- Gemfile
|
70
|
+
- Gemfile.lock
|
71
|
+
- LICENSE
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- lib/method_cacher.rb
|
75
|
+
- lib/method_cacher/base.rb
|
76
|
+
- lib/method_cacher/railtie.rb
|
77
|
+
- lib/method_cacher/version.rb
|
78
|
+
- method_cacher.gemspec
|
79
|
+
- spec/method_cacher/base_spec.rb
|
80
|
+
- spec/method_cacher/base_test_helper.rb
|
81
|
+
- spec/method_cacher_spec.rb
|
82
|
+
- spec/rspec_matchers.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
homepage: ''
|
85
|
+
licenses: []
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.8.10
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: Wraps specified instance and singleton methods with the Rails caching mechanism.
|
108
|
+
test_files:
|
109
|
+
- spec/method_cacher/base_spec.rb
|
110
|
+
- spec/method_cacher/base_test_helper.rb
|
111
|
+
- spec/method_cacher_spec.rb
|
112
|
+
- spec/rspec_matchers.rb
|
113
|
+
- spec/spec_helper.rb
|