garner 0.3.3 → 0.4.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.md +1 -1
- data/README.md +116 -135
- data/lib/garner/cache/binding.rb +58 -0
- data/lib/garner/cache/context.rb +27 -0
- data/lib/garner/cache/identity.rb +45 -0
- data/lib/garner/cache.rb +41 -0
- data/lib/garner/config.rb +46 -15
- data/lib/garner/mixins/mongoid/document.rb +75 -0
- data/lib/garner/mixins/mongoid/identity.rb +106 -0
- data/lib/garner/mixins/mongoid.rb +4 -0
- data/lib/garner/mixins/rack.rb +45 -0
- data/lib/garner/strategies/binding/invalidation/base.rb +26 -0
- data/lib/garner/strategies/binding/invalidation/touch.rb +27 -0
- data/lib/garner/strategies/binding/key/base.rb +19 -0
- data/lib/garner/strategies/binding/key/cache_key.rb +19 -0
- data/lib/garner/strategies/binding/key/safe_cache_key.rb +33 -0
- data/lib/garner/strategies/context/key/base.rb +21 -0
- data/lib/garner/strategies/context/key/caller.rb +83 -0
- data/lib/garner/strategies/context/key/jsonp.rb +30 -0
- data/lib/garner/strategies/context/key/request_get.rb +30 -0
- data/lib/garner/strategies/context/key/request_path.rb +28 -0
- data/lib/garner/strategies/context/key/request_post.rb +30 -0
- data/lib/garner/version.rb +1 -1
- data/lib/garner.rb +29 -26
- metadata +122 -22
- data/lib/garner/cache/object_identity.rb +0 -249
- data/lib/garner/middleware/base.rb +0 -47
- data/lib/garner/middleware/cache/bust.rb +0 -20
- data/lib/garner/mixins/grape_cache.rb +0 -111
- data/lib/garner/mixins/mongoid_document.rb +0 -58
- data/lib/garner/strategies/cache/expiration_strategy.rb +0 -16
- data/lib/garner/strategies/etags/grape_strategy.rb +0 -32
- data/lib/garner/strategies/etags/marshal_strategy.rb +0 -16
- data/lib/garner/strategies/keys/caller_strategy.rb +0 -38
- data/lib/garner/strategies/keys/jsonp_strategy.rb +0 -24
- data/lib/garner/strategies/keys/key_strategy.rb +0 -21
- data/lib/garner/strategies/keys/request_get_strategy.rb +0 -24
- data/lib/garner/strategies/keys/request_path_strategy.rb +0 -21
- data/lib/garner/strategies/keys/request_post_strategy.rb +0 -24
- data/lib/garner/strategies/keys/version_strategy.rb +0 -29
@@ -0,0 +1,75 @@
|
|
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
|
+
module Garner
|
11
|
+
module Mixins
|
12
|
+
module Mongoid
|
13
|
+
module Document
|
14
|
+
extend ActiveSupport::Concern
|
15
|
+
include Garner::Cache::Binding
|
16
|
+
|
17
|
+
def key_strategy
|
18
|
+
Garner.config.mongoid_binding_key_strategy
|
19
|
+
end
|
20
|
+
|
21
|
+
def invalidation_strategy
|
22
|
+
Garner.config.mongoid_binding_invalidation_strategy
|
23
|
+
end
|
24
|
+
|
25
|
+
included do
|
26
|
+
extend Garner::Cache::Binding
|
27
|
+
|
28
|
+
def self.cache_key
|
29
|
+
_latest_by_updated_at.try(:cache_key)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.touch
|
33
|
+
_latest_by_updated_at.try(:touch)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.updated_at
|
37
|
+
_latest_by_updated_at.try(:updated_at)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.key_strategy
|
41
|
+
Garner.config.mongoid_binding_key_strategy
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.invalidation_strategy
|
45
|
+
Garner.config.mongoid_binding_invalidation_strategy
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.identify(id)
|
49
|
+
Garner::Mixins::Mongoid::Identity.from_class_and_id(self, id)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.garnered_find(id)
|
53
|
+
return nil unless (binding = identify(id))
|
54
|
+
identity = Garner::Cache::Identity.new
|
55
|
+
identity.bind(binding).key({ :source => :garnered_find }) { find(id) }
|
56
|
+
end
|
57
|
+
|
58
|
+
after_create :_garner_after_create
|
59
|
+
after_update :_garner_after_update
|
60
|
+
after_destroy :_garner_after_destroy
|
61
|
+
|
62
|
+
protected
|
63
|
+
def self._latest_by_updated_at
|
64
|
+
# Only find the latest if we can order by :updated_at
|
65
|
+
return nil unless fields["updated_at"]
|
66
|
+
only(:_id, :_type, :updated_at).order_by({
|
67
|
+
:updated_at => :desc
|
68
|
+
}).first
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# Set up Garner configuration parameters
|
2
|
+
Garner.config.option(:mongoid_identity_fields, {
|
3
|
+
:default => [:_id]
|
4
|
+
})
|
5
|
+
|
6
|
+
module Garner
|
7
|
+
module Mixins
|
8
|
+
module Mongoid
|
9
|
+
class Identity
|
10
|
+
include Garner::Cache::Binding
|
11
|
+
|
12
|
+
attr_accessor :document, :collection_name, :conditions
|
13
|
+
|
14
|
+
def self.from_class_and_id(klass, id)
|
15
|
+
validate_class!(klass)
|
16
|
+
|
17
|
+
self.new.tap do |identity|
|
18
|
+
identity.collection_name = klass.collection_name
|
19
|
+
identity.conditions = conditions_for(klass, id)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@conditions = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def key_strategy
|
28
|
+
Garner.config.mongoid_binding_key_strategy
|
29
|
+
end
|
30
|
+
|
31
|
+
def invalidation_strategy
|
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
|
74
|
+
end
|
75
|
+
|
76
|
+
def _type
|
77
|
+
document["_type"] if document
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
def self.validate_class!(klass)
|
82
|
+
if !klass.include?(::Mongoid::Document)
|
83
|
+
raise "Must instantiate from a Mongoid class"
|
84
|
+
elsif klass.embedded?
|
85
|
+
raise "Cannot instantiate from an embedded document class"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.conditions_for(klass, id)
|
90
|
+
# multiple-ID conditions
|
91
|
+
conditions = {
|
92
|
+
"$or" => Garner.config.mongoid_identity_fields.map { |field|
|
93
|
+
{ field => id }
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
# _type conditions
|
98
|
+
selector = klass.where({})
|
99
|
+
conditions.merge!(selector.send(:type_selection)) if selector.send(:type_selectable?)
|
100
|
+
|
101
|
+
conditions
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "garner"
|
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
|
+
module Garner
|
14
|
+
module Mixins
|
15
|
+
module Rack
|
16
|
+
|
17
|
+
# Override this method to conditionally disable the cache.
|
18
|
+
#
|
19
|
+
# @return [Boolean]
|
20
|
+
def cache_enabled?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
# Instantiate a context-appropriate cache identity.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# garner.bind(current_user) do
|
28
|
+
# { count: current_user.logins.count }
|
29
|
+
# end
|
30
|
+
# @return [Garner::Cache::Identity] The cache identity.
|
31
|
+
def garner(&block)
|
32
|
+
identity = Garner::Cache::Identity.new
|
33
|
+
Garner.config.rack_context_key_strategies.each do |strategy|
|
34
|
+
identity = strategy.apply(identity, self)
|
35
|
+
end
|
36
|
+
|
37
|
+
unless cache_enabled?
|
38
|
+
identity.options({ :force_miss => true })
|
39
|
+
end
|
40
|
+
|
41
|
+
block_given? ? identity.fetch(&block) : identity
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Binding
|
4
|
+
module Invalidation
|
5
|
+
class 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
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Binding
|
4
|
+
module Invalidation
|
5
|
+
class Touch < 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
|
+
false
|
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
|
+
binding.touch if binding.respond_to?(:touch)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Binding
|
4
|
+
module Key
|
5
|
+
class Base
|
6
|
+
|
7
|
+
# Compute a cache key from an object binding.
|
8
|
+
#
|
9
|
+
# @param binding [Object] The object from which to compute a key.
|
10
|
+
# @return [String] A cache key string.
|
11
|
+
def self.apply(binding)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Binding
|
4
|
+
module Key
|
5
|
+
class CacheKey < Base
|
6
|
+
|
7
|
+
# Compute a cache key from an object binding.
|
8
|
+
#
|
9
|
+
# @param binding [Object] The object from which to compute a key.
|
10
|
+
# @return [String] A cache key string.
|
11
|
+
def self.apply(binding)
|
12
|
+
binding.cache_key if binding.respond_to?(:cache_key)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Binding
|
4
|
+
module Key
|
5
|
+
class SafeCacheKey < Base
|
6
|
+
VALID_FORMAT = /^(?<model>[^\/]+)\/(?<id>.+)-(?<timestamp>[0-9]{14})$/
|
7
|
+
|
8
|
+
# Compute a cache key from an object binding. Only return a key if
|
9
|
+
# :cache_key and :updated_at are both defined and present on the
|
10
|
+
# object, and if :cache_key conforms to the ActiveModel format.
|
11
|
+
#
|
12
|
+
# If all requirements are met, append the millisecond portion of
|
13
|
+
# :updated_at to :cache_key.
|
14
|
+
#
|
15
|
+
# @param binding [Object] The object from which to compute a key.
|
16
|
+
# @return [String] A cache key string.
|
17
|
+
def self.apply(binding)
|
18
|
+
return unless binding.respond_to?(:cache_key) && binding.cache_key
|
19
|
+
return unless binding.respond_to?(:updated_at) && binding.updated_at
|
20
|
+
|
21
|
+
# Check for ActiveModel cache key format
|
22
|
+
return unless binding.cache_key =~ VALID_FORMAT
|
23
|
+
|
24
|
+
decimal_portion = binding.updated_at.utc.to_f % 1
|
25
|
+
decimal_string = sprintf("%.10f", decimal_portion).gsub(/^0/, "")
|
26
|
+
"#{binding.cache_key}#{decimal_string}"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Context
|
4
|
+
module Key
|
5
|
+
class Base
|
6
|
+
|
7
|
+
# Compute a hash of key-value pairs from a given ruby context,
|
8
|
+
# and apply it to a cache identity.
|
9
|
+
#
|
10
|
+
# @param identity [Garner::Cache::Identity] The cache identity.
|
11
|
+
# @param ruby_context [Object] An optional Ruby context.
|
12
|
+
# @return [Garner::Cache::Identity] The modified identity.
|
13
|
+
def self.apply(identity, ruby_context = self)
|
14
|
+
identity
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Context
|
4
|
+
module Key
|
5
|
+
class Caller < Base
|
6
|
+
|
7
|
+
def self.field
|
8
|
+
:caller
|
9
|
+
end
|
10
|
+
|
11
|
+
# Determine the most likely root path for the current Garner client
|
12
|
+
# application. If in a Rails application, Rails.root is used.
|
13
|
+
# Otherwise, the nearest ancestor directory containing a Gemfile is
|
14
|
+
# used.
|
15
|
+
#
|
16
|
+
# @see Garner::Config#caller_root=
|
17
|
+
# @see Garner::Config#default_caller_root
|
18
|
+
# @return [String] The default root path.
|
19
|
+
def self.default_root
|
20
|
+
if defined?(::Rails) && ::Rails.respond_to?(:root)
|
21
|
+
::Rails.root
|
22
|
+
else
|
23
|
+
# Try to use the nearest ancestor directory containing a Gemfile.
|
24
|
+
requiring_caller = send(:caller).detect do |line|
|
25
|
+
!line.include?(File.join("lib", "garner"))
|
26
|
+
end
|
27
|
+
return nil unless requiring_caller
|
28
|
+
|
29
|
+
requiring_file = requiring_caller.split(":")[0]
|
30
|
+
gemfile_root(File.dirname(requiring_file))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Injects the caller's location into the key hash.
|
35
|
+
#
|
36
|
+
# @param identity [Garner::Cache::Identity] The cache identity.
|
37
|
+
# @param ruby_context [Object] An optional Ruby context.
|
38
|
+
# @return [Garner::Cache::Identity] The modified identity.
|
39
|
+
def self.apply(identity, ruby_context = self)
|
40
|
+
value = nil
|
41
|
+
|
42
|
+
if ruby_context.send(:caller)
|
43
|
+
ruby_context.send(:caller).compact.each do |line|
|
44
|
+
parts = line.match(/(?<filename>[^:]+)\:(?<lineno>[^:]+)/)
|
45
|
+
file = (Pathname.new(parts[:filename]).realpath.to_s rescue nil)
|
46
|
+
next if file.nil? || file == ""
|
47
|
+
next if file.include?(File.join("lib", "garner"))
|
48
|
+
|
49
|
+
if (root = Garner.config.caller_root)
|
50
|
+
root += File::SEPARATOR unless root[-1] == File::SEPARATOR
|
51
|
+
next unless file =~ /^#{root}/
|
52
|
+
value = "#{file.gsub(root || "", "")}:#{parts[:lineno]}"
|
53
|
+
else
|
54
|
+
value = "#{file}:#{parts[:lineno]}"
|
55
|
+
end
|
56
|
+
|
57
|
+
break
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
value ? identity.key(field => value) : identity
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def self.gemfile_root(path)
|
66
|
+
path = Pathname.new(path).realpath.to_s
|
67
|
+
newpath = Pathname.new(File.join(path, "..")).realpath.to_s
|
68
|
+
if newpath == path
|
69
|
+
# We've reached the filesystem root; return
|
70
|
+
return nil
|
71
|
+
elsif File.exist?(File.join(newpath, "Gemfile"))
|
72
|
+
# We've struck Gemfile gold; return current path
|
73
|
+
return newpath
|
74
|
+
else
|
75
|
+
return gemfile_root(newpath)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Context
|
4
|
+
module Key
|
5
|
+
class Jsonp < Base
|
6
|
+
|
7
|
+
def self.field
|
8
|
+
:request_params
|
9
|
+
end
|
10
|
+
|
11
|
+
# Strips JSONP parameters from the key.
|
12
|
+
#
|
13
|
+
# @param identity [Garner::Cache::Identity] The cache identity.
|
14
|
+
# @param ruby_context [Object] An optional Ruby context.
|
15
|
+
# @return [Garner::Cache::Identity] The modified identity.
|
16
|
+
def self.apply(identity, ruby_context = self)
|
17
|
+
key_hash = identity.key_hash
|
18
|
+
return identity unless key_hash[field]
|
19
|
+
|
20
|
+
|
21
|
+
key_hash[field].delete("callback")
|
22
|
+
key_hash[field].delete("_")
|
23
|
+
identity
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Context
|
4
|
+
module Key
|
5
|
+
class RequestGet < Base
|
6
|
+
|
7
|
+
def self.field
|
8
|
+
:request_params
|
9
|
+
end
|
10
|
+
|
11
|
+
# Injects the request GET parameters into the key hash.
|
12
|
+
#
|
13
|
+
# @param identity [Garner::Cache::Identity] The cache identity.
|
14
|
+
# @param ruby_context [Object] An optional Ruby context.
|
15
|
+
# @return [Garner::Cache::Identity] The modified identity.
|
16
|
+
def self.apply(identity, ruby_context = self)
|
17
|
+
return identity unless (ruby_context.respond_to?(:request))
|
18
|
+
|
19
|
+
request = ruby_context.request
|
20
|
+
if request && ["GET", "HEAD"].include?(request.request_method)
|
21
|
+
identity.key(field => request.GET.dup)
|
22
|
+
end
|
23
|
+
identity
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Context
|
4
|
+
module Key
|
5
|
+
class RequestPath < Base
|
6
|
+
|
7
|
+
def self.field
|
8
|
+
:request_path
|
9
|
+
end
|
10
|
+
|
11
|
+
# Injects the request path into the key hash.
|
12
|
+
#
|
13
|
+
# @param identity [Garner::Cache::Identity] The cache identity.
|
14
|
+
# @param ruby_context [Object] An optional Ruby context.
|
15
|
+
# @return [Garner::Cache::Identity] The modified identity.
|
16
|
+
def self.apply(identity, ruby_context = self)
|
17
|
+
return identity unless (ruby_context.respond_to?(:request))
|
18
|
+
|
19
|
+
request = ruby_context.request
|
20
|
+
identity.key(field => request.path) if request.respond_to?(:path)
|
21
|
+
identity
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Garner
|
2
|
+
module Strategies
|
3
|
+
module Context
|
4
|
+
module Key
|
5
|
+
class RequestPost < Base
|
6
|
+
|
7
|
+
def self.field
|
8
|
+
:request_params
|
9
|
+
end
|
10
|
+
|
11
|
+
# Injects the request POST parameters into the key hash.
|
12
|
+
#
|
13
|
+
# @param identity [Garner::Cache::Identity] The cache identity.
|
14
|
+
# @param ruby_context [Object] An optional Ruby context.
|
15
|
+
# @return [Garner::Cache::Identity] The modified identity.
|
16
|
+
def self.apply(identity, ruby_context = self)
|
17
|
+
return identity unless (ruby_context.respond_to?(:request))
|
18
|
+
|
19
|
+
request = ruby_context.request
|
20
|
+
if request.request_method == "POST"
|
21
|
+
identity = identity.key(field => request.POST.dup)
|
22
|
+
end
|
23
|
+
identity
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/garner/version.rb
CHANGED
data/lib/garner.rb
CHANGED
@@ -1,26 +1,29 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
require
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
require
|
19
|
-
require
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
require
|
24
|
-
|
25
|
-
|
26
|
-
require
|
1
|
+
require "multi_json"
|
2
|
+
require "active_support"
|
3
|
+
|
4
|
+
# Garner core
|
5
|
+
require "garner/version"
|
6
|
+
require "garner/config"
|
7
|
+
|
8
|
+
# Key strategies
|
9
|
+
require "garner/strategies/context/key/base"
|
10
|
+
require "garner/strategies/context/key/caller"
|
11
|
+
require "garner/strategies/context/key/request_path"
|
12
|
+
require "garner/strategies/context/key/request_get"
|
13
|
+
require "garner/strategies/context/key/request_post"
|
14
|
+
require "garner/strategies/context/key/jsonp"
|
15
|
+
|
16
|
+
# Binding strategies
|
17
|
+
require "garner/strategies/binding/key/base"
|
18
|
+
require "garner/strategies/binding/key/cache_key"
|
19
|
+
require "garner/strategies/binding/key/safe_cache_key"
|
20
|
+
|
21
|
+
# Invalidation strategies
|
22
|
+
require "garner/strategies/binding/invalidation/base"
|
23
|
+
require "garner/strategies/binding/invalidation/touch"
|
24
|
+
|
25
|
+
# Cache
|
26
|
+
require "garner/cache"
|
27
|
+
require "garner/cache/identity"
|
28
|
+
require "garner/cache/context"
|
29
|
+
require "garner/cache/binding"
|