garner 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +15 -8
- data/lib/garner.rb +2 -0
- data/lib/garner/cache/binding.rb +8 -0
- data/lib/garner/cache/context.rb +8 -0
- data/lib/garner/mixins/active_record.rb +4 -0
- data/lib/garner/mixins/active_record/base.rb +17 -0
- data/lib/garner/mixins/mongoid.rb +1 -0
- data/lib/garner/mixins/mongoid/document.rb +29 -34
- data/lib/garner/mixins/mongoid/identity.rb +23 -60
- data/lib/garner/mixins/rack.rb +0 -10
- data/lib/garner/strategies/binding/invalidation/binding_index.rb +35 -0
- data/lib/garner/strategies/binding/invalidation/touch.rb +15 -1
- data/lib/garner/strategies/binding/key/binding_index.rb +109 -0
- data/lib/garner/strategies/binding/key/safe_cache_key.rb +2 -0
- data/lib/garner/version.rb +1 -1
- metadata +23 -3
data/README.md
CHANGED
@@ -5,11 +5,10 @@ Garner is a cache layer for Ruby and Rack applications, supporting model and ins
|
|
5
5
|
|
6
6
|
If you're not familiar with HTTP caching, ETags and If-Modified-Since, watch us introduce Garner in [From Zero to API Cache in 10 Minutes](http://www.confreaks.com/videos/986-goruco2012-from-zero-to-api-cache-w-grape-mongodb-in-10-minutes) at GoRuCo 2012.
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
Upgrading
|
9
|
+
---------
|
10
10
|
|
11
|
-
|
12
|
-
The current stable release is [0.3.3](https://github.com/artsy/garner/blob/v0.3.3/README.md).
|
11
|
+
The current stable release of Garner is 0.4.1, and contains many breaking changes from the previous stable release, 0.3.3. For a summary of important changes, see [UPGRADING](UPGRADING.md).
|
13
12
|
|
14
13
|
Usage
|
15
14
|
-----
|
@@ -111,7 +110,17 @@ Order.find(3).invalidate_garner_caches
|
|
111
110
|
|
112
111
|
### ActiveRecord
|
113
112
|
|
114
|
-
Garner provides rudimentary support for `ActiveRecord`.
|
113
|
+
Garner provides rudimentary support for `ActiveRecord`. To use ActiveRecord models for Garner bindings, use `Garner::Mixins::ActiveRecord::Base`. You can set it up in an initializer:
|
114
|
+
|
115
|
+
``` ruby
|
116
|
+
require "garner/mixins/active_record"
|
117
|
+
|
118
|
+
module ActiveRecord
|
119
|
+
class Base
|
120
|
+
include Garner::Mixins::ActiveRecord::Base
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
115
124
|
|
116
125
|
|
117
126
|
Under The Hood: Bindings
|
@@ -133,7 +142,7 @@ end
|
|
133
142
|
|
134
143
|
Binding keys are computed via pluggable strategies, as are the rules for invalidating caches when a binding changes. By default, Garner uses `Garner::Strategies::Binding::Key::SafeCacheKey` to compute binding keys: this uses `cache_key` if defined on an object; otherwise it always bypasses cache. Similarly, Garner uses `Garner::Strategies::Binding::Invalidation::Touch` as its default invalidation strategy. This will call `:touch` on a document if it is defined; otherwise it will take no action.
|
135
144
|
|
136
|
-
Additional binding and invalidation strategies can be written. To use them, set `Garner.config.binding_key_strategy` and `Garner.config.binding_invalidation_strategy`.
|
145
|
+
Additional binding and invalidation strategies can be written. To use them, set `Garner.config.binding_key_strategy` and `Garner.config.binding_invalidation_strategy`.
|
137
146
|
|
138
147
|
|
139
148
|
Under The Hood: Cache Context Keys
|
@@ -185,8 +194,6 @@ The full list of `Garner.config` attributes is:
|
|
185
194
|
```
|
186
195
|
* `:binding_key_strategy`: Binding key strategy. Defaults to `Garner::Strategies::Binding::Key::SafeCacheKey`.
|
187
196
|
* `:binding_invalidation_strategy`: Binding invalidation strategy. Defaults to `Garner::Strategies::Binding::Invalidation::Touch`.
|
188
|
-
* `:mongoid_binding_key_strategy`: Mongoid-specific binding key strategy. Defaults to `Garner::Strategies::Binding::Key::SafeCacheKey`.
|
189
|
-
* `:mongoid_binding_invalidation_strategy`: Mongoid-specific binding invalidation strategy. Defaults to `Garner::Strategies::Binding::Invalidation::Touch`.
|
190
197
|
* `:mongoid_identity_fields`: Identity fields considered legal for the `identity` method. Defaults to `[:_id]`.
|
191
198
|
* `:caller_root`: Root path of application, to be stripped out of value strings generated by the `Caller` context key strategy. Defaults to `Rails.root` if in a Rails environment; otherwise to the nearest ancestor directory containing a Gemfile.
|
192
199
|
|
data/lib/garner.rb
CHANGED
@@ -17,10 +17,12 @@ require "garner/strategies/context/key/jsonp"
|
|
17
17
|
require "garner/strategies/binding/key/base"
|
18
18
|
require "garner/strategies/binding/key/cache_key"
|
19
19
|
require "garner/strategies/binding/key/safe_cache_key"
|
20
|
+
require "garner/strategies/binding/key/binding_index"
|
20
21
|
|
21
22
|
# Invalidation strategies
|
22
23
|
require "garner/strategies/binding/invalidation/base"
|
23
24
|
require "garner/strategies/binding/invalidation/touch"
|
25
|
+
require "garner/strategies/binding/invalidation/binding_index"
|
24
26
|
|
25
27
|
# Cache
|
26
28
|
require "garner/cache"
|
data/lib/garner/cache/binding.rb
CHANGED
@@ -5,6 +5,9 @@ Garner.config.option(:binding_key_strategy, {
|
|
5
5
|
Garner.config.option(:binding_invalidation_strategy, {
|
6
6
|
:default => Garner::Strategies::Binding::Invalidation::Touch
|
7
7
|
})
|
8
|
+
Garner.config.option(:mongoid_identity_fields, {
|
9
|
+
:default => [:_id]
|
10
|
+
})
|
8
11
|
|
9
12
|
module Garner
|
10
13
|
module Cache
|
@@ -18,6 +21,8 @@ module Garner
|
|
18
21
|
end
|
19
22
|
|
20
23
|
# Apply the cache key strategy to this binding.
|
24
|
+
#
|
25
|
+
# @return [String] A cache key string.
|
21
26
|
def garner_cache_key
|
22
27
|
key_strategy.apply(self)
|
23
28
|
end
|
@@ -30,8 +35,11 @@ module Garner
|
|
30
35
|
end
|
31
36
|
|
32
37
|
# Apply the invalidation strategy to this binding.
|
38
|
+
#
|
39
|
+
# @return [Boolean] Returns true on success.
|
33
40
|
def invalidate_garner_caches
|
34
41
|
invalidation_strategy.apply(self)
|
42
|
+
true
|
35
43
|
end
|
36
44
|
|
37
45
|
protected
|
data/lib/garner/cache/context.rb
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
Garner.config.option(:context_key_strategies, {
|
3
3
|
:default => [Garner::Strategies::Context::Key::Caller]
|
4
4
|
})
|
5
|
+
Garner.config.option(:rack_context_key_strategies, {
|
6
|
+
:default => [
|
7
|
+
Garner::Strategies::Context::Key::Caller,
|
8
|
+
Garner::Strategies::Context::Key::RequestGet,
|
9
|
+
Garner::Strategies::Context::Key::RequestPost,
|
10
|
+
Garner::Strategies::Context::Key::RequestPath
|
11
|
+
]
|
12
|
+
})
|
5
13
|
|
6
14
|
module Garner
|
7
15
|
module Cache
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "garner"
|
2
|
+
require "active_record"
|
3
|
+
|
4
|
+
module Garner
|
5
|
+
module Mixins
|
6
|
+
module ActiveRecord
|
7
|
+
module Base
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
include Garner::Cache::Binding
|
10
|
+
|
11
|
+
included do
|
12
|
+
extend Garner::Cache::Binding
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,12 +1,3 @@
|
|
1
|
-
# Set up Garner configuration parameters
|
2
|
-
Garner.config.option(:mongoid_binding_key_strategy, {
|
3
|
-
:default => Garner.config.binding_key_strategy
|
4
|
-
})
|
5
|
-
|
6
|
-
Garner.config.option(:mongoid_binding_invalidation_strategy, {
|
7
|
-
:default => Garner.config.binding_invalidation_strategy
|
8
|
-
})
|
9
|
-
|
10
1
|
module Garner
|
11
2
|
module Mixins
|
12
3
|
module Mongoid
|
@@ -14,45 +5,49 @@ module Garner
|
|
14
5
|
extend ActiveSupport::Concern
|
15
6
|
include Garner::Cache::Binding
|
16
7
|
|
17
|
-
def
|
18
|
-
|
8
|
+
def proxied_classes
|
9
|
+
self.class.mongoid_superclasses
|
19
10
|
end
|
20
11
|
|
21
|
-
def
|
22
|
-
|
12
|
+
def identity_string
|
13
|
+
"#{self.class.name}/id=#{id}"
|
23
14
|
end
|
24
15
|
|
25
16
|
included do
|
26
17
|
extend Garner::Cache::Binding
|
27
18
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
_latest_by_updated_at.try(:updated_at)
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.key_strategy
|
41
|
-
Garner.config.mongoid_binding_key_strategy
|
19
|
+
# Return an array of this class and all Mongoid superclasses.
|
20
|
+
#
|
21
|
+
# @return [Array] An array of classes.
|
22
|
+
def self.mongoid_superclasses
|
23
|
+
if superclass.include?(Mongoid::Document)
|
24
|
+
[self] + superclass.mongoid_superclasses
|
25
|
+
else
|
26
|
+
[self]
|
27
|
+
end
|
42
28
|
end
|
43
29
|
|
44
|
-
|
45
|
-
|
30
|
+
# Return an object that can act as a binding on this class's behalf.
|
31
|
+
#
|
32
|
+
# @return [Mongoid::Document]
|
33
|
+
def self.proxy_binding
|
34
|
+
_latest_by_updated_at
|
46
35
|
end
|
47
36
|
|
48
|
-
def self.identify(
|
49
|
-
|
37
|
+
def self.identify(handle)
|
38
|
+
Mongoid::Identity.from_class_and_handle(self, handle)
|
50
39
|
end
|
51
40
|
|
52
|
-
|
53
|
-
|
41
|
+
# Find an object by _id, or other findable field, first trying to
|
42
|
+
# fetch from Garner's cache.
|
43
|
+
#
|
44
|
+
# @return [Mongoid::Document]
|
45
|
+
def self.garnered_find(handle)
|
46
|
+
return nil unless (binding = identify(handle))
|
54
47
|
identity = Garner::Cache::Identity.new
|
55
|
-
identity.bind(binding).key({ :source => :garnered_find })
|
48
|
+
identity.bind(binding).key({ :source => :garnered_find }) do
|
49
|
+
find(handle)
|
50
|
+
end
|
56
51
|
end
|
57
52
|
|
58
53
|
after_create :_garner_after_create
|
@@ -1,22 +1,24 @@
|
|
1
|
-
# Set up Garner configuration parameters
|
2
|
-
Garner.config.option(:mongoid_identity_fields, {
|
3
|
-
:default => [:_id]
|
4
|
-
})
|
5
|
-
|
6
1
|
module Garner
|
7
2
|
module Mixins
|
8
3
|
module Mongoid
|
9
4
|
class Identity
|
10
5
|
include Garner::Cache::Binding
|
11
6
|
|
12
|
-
attr_accessor :
|
7
|
+
attr_accessor :klass, :handle, :proxy_binding, :conditions
|
13
8
|
|
14
|
-
|
9
|
+
# Instantiate a new Mongoid::Identity.
|
10
|
+
#
|
11
|
+
# @param klass [Class] A
|
12
|
+
# @param handle [Object] A String, Fixnum, BSON::ObjectId, etc.
|
13
|
+
# identifying the object.
|
14
|
+
# @return [Garner::Mixins::Mongoid::Identity]
|
15
|
+
def self.from_class_and_handle(klass, handle)
|
15
16
|
validate_class!(klass)
|
16
17
|
|
17
18
|
self.new.tap do |identity|
|
18
|
-
identity.
|
19
|
-
identity.
|
19
|
+
identity.klass = klass
|
20
|
+
identity.handle = handle
|
21
|
+
identity.conditions = conditions_for(klass, handle)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
@@ -24,57 +26,18 @@ module Garner
|
|
24
26
|
@conditions = {}
|
25
27
|
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
Garner.config.mongoid_binding_invalidation_strategy
|
33
|
-
end
|
34
|
-
|
35
|
-
def cache_key
|
36
|
-
# See https://github.com/mongoid/mongoid/blob/f5ba1295/lib/mongoid/document.rb#L242
|
37
|
-
if updated_at
|
38
|
-
"#{model_cache_key}/#{_id}-#{updated_at.utc.to_s(:number)}"
|
39
|
-
elsif _id
|
40
|
-
"#{model_cache_key}/#{_id}"
|
41
|
-
else
|
42
|
-
"#{model_cache_key}/new"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def model_cache_key
|
47
|
-
if _type
|
48
|
-
ActiveModel::Name.new(_type.constantize).cache_key
|
49
|
-
else
|
50
|
-
@collection_name.to_s
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def collection
|
55
|
-
::Mongoid.default_session[@collection_name]
|
56
|
-
end
|
57
|
-
|
58
|
-
def document
|
59
|
-
return @document if @document
|
60
|
-
|
61
|
-
collection.where(@conditions).select({
|
62
|
-
:_id => 1,
|
63
|
-
:_type => 1,
|
64
|
-
:updated_at => 1
|
65
|
-
}).limit(1).first
|
66
|
-
end
|
67
|
-
|
68
|
-
def _id
|
69
|
-
document["_id"] if document
|
70
|
-
end
|
71
|
-
|
72
|
-
def updated_at
|
73
|
-
document["updated_at"] if document
|
29
|
+
# Return an object that can act as a binding on this identity's behalf.
|
30
|
+
#
|
31
|
+
# @return [Mongoid::Document]
|
32
|
+
def proxy_binding
|
33
|
+
@proxy_binding ||= klass.where(conditions).only(:_id, :_type, :updated_at).first
|
74
34
|
end
|
75
35
|
|
76
|
-
|
77
|
-
|
36
|
+
# Stringize this identity for purposes of marshaling.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
def to_s
|
40
|
+
"#{self.class.name}/klass=#{klass},handle=#{handle}"
|
78
41
|
end
|
79
42
|
|
80
43
|
private
|
@@ -86,11 +49,11 @@ module Garner
|
|
86
49
|
end
|
87
50
|
end
|
88
51
|
|
89
|
-
def self.conditions_for(klass,
|
52
|
+
def self.conditions_for(klass, handle)
|
90
53
|
# multiple-ID conditions
|
91
54
|
conditions = {
|
92
55
|
"$or" => Garner.config.mongoid_identity_fields.map { |field|
|
93
|
-
{ field =>
|
56
|
+
{ field => handle }
|
94
57
|
}
|
95
58
|
}
|
96
59
|
|
data/lib/garner/mixins/rack.rb
CHANGED
@@ -1,15 +1,5 @@
|
|
1
1
|
require "garner"
|
2
2
|
|
3
|
-
# Set up Garner configuration parameters
|
4
|
-
Garner.config.option(:rack_context_key_strategies, {
|
5
|
-
:default => [
|
6
|
-
Garner::Strategies::Context::Key::Caller,
|
7
|
-
Garner::Strategies::Context::Key::RequestGet,
|
8
|
-
Garner::Strategies::Context::Key::RequestPost,
|
9
|
-
Garner::Strategies::Context::Key::RequestPath
|
10
|
-
]
|
11
|
-
})
|
12
|
-
|
13
3
|
module Garner
|
14
4
|
module Mixins
|
15
5
|
module Rack
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Binding
|
4
|
+
module Invalidation
|
5
|
+
class BindingIndex < Base
|
6
|
+
|
7
|
+
# Specifies whether invalidation should happen on callbacks.
|
8
|
+
#
|
9
|
+
# @param kind [Symbol] One of :create, :update, :destroy
|
10
|
+
def self.apply_on_callback?(kind = nil)
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
# Force-invalidate an object binding. Used when bindings are
|
15
|
+
# explicitly invalidated, via binding.invalidate_garner_caches.
|
16
|
+
#
|
17
|
+
# @param binding [Object] The binding whose caches are to be
|
18
|
+
# invalidated.
|
19
|
+
def self.apply(binding)
|
20
|
+
Key::BindingIndex.write_canonical_binding_for(binding)
|
21
|
+
Key::BindingIndex.write_cache_key_for(binding)
|
22
|
+
|
23
|
+
# Invalidate proxied classes
|
24
|
+
if binding.respond_to?(:proxied_classes)
|
25
|
+
binding.proxied_classes.each do |klass|
|
26
|
+
Key::BindingIndex.write_cache_key_for(klass)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -8,7 +8,10 @@ module Garner
|
|
8
8
|
#
|
9
9
|
# @param kind [Symbol] One of :create, :update, :destroy
|
10
10
|
def self.apply_on_callback?(kind = nil)
|
11
|
-
|
11
|
+
# Only apply on destruction, so that class bindings remain
|
12
|
+
# valid, if the destroyed binding was not also the previous
|
13
|
+
# proxy_binding.
|
14
|
+
!!(kind == :destroy)
|
12
15
|
end
|
13
16
|
|
14
17
|
# Force-invalidate an object binding. Used when bindings are
|
@@ -17,6 +20,17 @@ module Garner
|
|
17
20
|
# @param binding [Object] The binding whose caches are to be
|
18
21
|
# invalidated.
|
19
22
|
def self.apply(binding)
|
23
|
+
if binding.respond_to?(:destroyed?) &&
|
24
|
+
binding.destroyed? &&
|
25
|
+
binding.class.respond_to?(:proxy_binding)
|
26
|
+
# Binding is destroyed, but we must ensure that its class's
|
27
|
+
# proxy_binding is touched, if necessary.
|
28
|
+
binding = binding.class.proxy_binding
|
29
|
+
|
30
|
+
elsif binding.respond_to?(:proxy_binding)
|
31
|
+
binding = binding.proxy_binding
|
32
|
+
end
|
33
|
+
|
20
34
|
binding.touch if binding.respond_to?(:touch)
|
21
35
|
end
|
22
36
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Binding
|
4
|
+
module Key
|
5
|
+
class BindingIndex < Base
|
6
|
+
RANDOM_KEY_LENGTH = 12 # In bytes.
|
7
|
+
|
8
|
+
# Compute a cache key as follows:
|
9
|
+
# 1. Determine whether the binding is canonical.
|
10
|
+
# 2. If canonical, fetch the cache key stored for binding.class,
|
11
|
+
# binding.id
|
12
|
+
# 3. If not canonical, determine the canonical ID from a proxy
|
13
|
+
# binding. Proxy bindings must implement `proxy_binding` and
|
14
|
+
# `handle`.
|
15
|
+
#
|
16
|
+
# @param binding [Object] The object from which to compute a key.
|
17
|
+
# @return [String] A cache key string.
|
18
|
+
def self.apply(binding)
|
19
|
+
fetch_cache_key_for(binding)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Fetch cache key, from cache, for the given binding. Generate a
|
23
|
+
# random key, if not already extant.
|
24
|
+
#
|
25
|
+
# @param binding [Object] The object from which to compute a key.
|
26
|
+
# @return [String] A cache key string.
|
27
|
+
def self.fetch_cache_key_for(binding)
|
28
|
+
canonical_binding = fetch_canonical_binding_for(binding)
|
29
|
+
key = index_key_for(canonical_binding)
|
30
|
+
Garner.config.cache.fetch(key) { new_cache_key_for(canonical_binding) }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Overwrite cache key for the given binding.
|
34
|
+
#
|
35
|
+
# @param binding [Object] The object from which to compute a key.
|
36
|
+
# @return [String] A cache key string.
|
37
|
+
def self.write_cache_key_for(binding)
|
38
|
+
canonical_binding = fetch_canonical_binding_for(binding)
|
39
|
+
key = index_key_for(canonical_binding)
|
40
|
+
value = new_cache_key_for(canonical_binding)
|
41
|
+
value.tap { |v| Garner.config.cache.write(key, v) }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Fetch canonical binding for the given binding.
|
45
|
+
#
|
46
|
+
# @param binding [Object] The object from which to compute a key.
|
47
|
+
# @return [Object] A class, ID pair.
|
48
|
+
def self.fetch_canonical_binding_for(binding)
|
49
|
+
return binding if canonical?(binding)
|
50
|
+
key = index_key_for(binding)
|
51
|
+
Garner.config.cache.fetch(key) { canonical_binding_for(binding) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Overwrite canonical binding for the given binding.
|
55
|
+
#
|
56
|
+
# @param binding [Object] The object from which to compute a key.
|
57
|
+
# @return [Object] A class, ID pair.
|
58
|
+
def self.write_canonical_binding_for(binding)
|
59
|
+
return binding if canonical?(binding)
|
60
|
+
key = index_key_for(binding)
|
61
|
+
value = canonical_binding_for(binding)
|
62
|
+
value.tap { |v| Garner.config.cache.write(key, v) }
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return canonical binding for the given binding.
|
66
|
+
#
|
67
|
+
# @param binding [Object] The (possibly) non-canonical binding.
|
68
|
+
# @return binding [Object] The canonical binding.
|
69
|
+
def self.canonical_binding_for(binding)
|
70
|
+
if canonical?(binding)
|
71
|
+
binding
|
72
|
+
elsif binding.respond_to?(:proxy_binding)
|
73
|
+
canonical_binding_for(binding.proxy_binding)
|
74
|
+
else
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Determine whether the given binding is canonical.
|
80
|
+
#
|
81
|
+
# @return [Boolean]
|
82
|
+
def self.canonical?(binding)
|
83
|
+
# TODO: Implement real logic for determining canonicity.
|
84
|
+
binding.is_a?(Mongoid::Document) ||
|
85
|
+
(binding.is_a?(Class) && binding.include?(Mongoid::Document))
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
def self.index_key_for(binding)
|
90
|
+
if binding.respond_to?(:identity_string)
|
91
|
+
binding_key = binding.identity_string
|
92
|
+
else
|
93
|
+
binding_key = binding.to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
{
|
97
|
+
:strategy => self,
|
98
|
+
:proxied_binding => binding_key
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.new_cache_key_for(binding)
|
103
|
+
SecureRandom.hex(RANDOM_KEY_LENGTH)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -15,6 +15,8 @@ module Garner
|
|
15
15
|
# @param binding [Object] The object from which to compute a key.
|
16
16
|
# @return [String] A cache key string.
|
17
17
|
def self.apply(binding)
|
18
|
+
binding = binding.proxy_binding if binding.respond_to?(:proxy_binding)
|
19
|
+
|
18
20
|
return unless binding.respond_to?(:cache_key) && binding.cache_key
|
19
21
|
return unless binding.respond_to?(:updated_at) && binding.updated_at
|
20
22
|
|
data/lib/garner/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: garner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-06-
|
13
|
+
date: 2013-06-28 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -268,6 +268,22 @@ dependencies:
|
|
268
268
|
- - ! '>='
|
269
269
|
- !ruby/object:Gem::Version
|
270
270
|
version: '0'
|
271
|
+
- !ruby/object:Gem::Dependency
|
272
|
+
name: method_profiler
|
273
|
+
requirement: !ruby/object:Gem::Requirement
|
274
|
+
none: false
|
275
|
+
requirements:
|
276
|
+
- - ! '>='
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
279
|
+
type: :development
|
280
|
+
prerelease: false
|
281
|
+
version_requirements: !ruby/object:Gem::Requirement
|
282
|
+
none: false
|
283
|
+
requirements:
|
284
|
+
- - ! '>='
|
285
|
+
- !ruby/object:Gem::Version
|
286
|
+
version: '0'
|
271
287
|
- !ruby/object:Gem::Dependency
|
272
288
|
name: pry
|
273
289
|
requirement: !ruby/object:Gem::Requirement
|
@@ -347,13 +363,17 @@ files:
|
|
347
363
|
- lib/garner/cache/context.rb
|
348
364
|
- lib/garner/cache/identity.rb
|
349
365
|
- lib/garner/config.rb
|
366
|
+
- lib/garner/mixins/active_record.rb
|
367
|
+
- lib/garner/mixins/active_record/base.rb
|
350
368
|
- lib/garner/mixins/mongoid.rb
|
351
369
|
- lib/garner/mixins/mongoid/document.rb
|
352
370
|
- lib/garner/mixins/mongoid/identity.rb
|
353
371
|
- lib/garner/mixins/rack.rb
|
354
372
|
- lib/garner/strategies/binding/invalidation/base.rb
|
373
|
+
- lib/garner/strategies/binding/invalidation/binding_index.rb
|
355
374
|
- lib/garner/strategies/binding/invalidation/touch.rb
|
356
375
|
- lib/garner/strategies/binding/key/base.rb
|
376
|
+
- lib/garner/strategies/binding/key/binding_index.rb
|
357
377
|
- lib/garner/strategies/binding/key/cache_key.rb
|
358
378
|
- lib/garner/strategies/binding/key/safe_cache_key.rb
|
359
379
|
- lib/garner/strategies/context/key/base.rb
|
@@ -380,7 +400,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
380
400
|
version: '0'
|
381
401
|
segments:
|
382
402
|
- 0
|
383
|
-
hash:
|
403
|
+
hash: 1915990174138923704
|
384
404
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
385
405
|
none: false
|
386
406
|
requirements:
|