garner 0.4.0 → 0.4.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/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:
|