cachier 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,104 @@
1
+ # Cachier
2
+ module Cachier
3
+ extend self
4
+
5
+ CACHE_KEY = 'cachier-tags'
6
+
7
+ def perform_caching?
8
+ ::ApplicationController.perform_caching
9
+ end
10
+
11
+ # Fetch from cache, this function accepts a block
12
+ def fetch(cache_key, cache_params = {})
13
+ tags = cache_params.delete(:tag) || []
14
+ store_fragment(cache_key, tags)
15
+
16
+ if block_given?
17
+ returned_object = Rails.cache.fetch(cache_key, cache_params) {
18
+ yield
19
+ }
20
+ else
21
+ Rails.cache.read(cache_key)
22
+ end
23
+ end
24
+
25
+ def store_fragment(fragment, *tags)
26
+ return unless perform_caching?
27
+
28
+ tags.each do |tag|
29
+ fragments = Rails.cache.fetch(tag) || []
30
+ Rails.cache.write(tag, fragments + [fragment])
31
+ end
32
+
33
+ add_tags_to_tag_list(tags)
34
+ end
35
+
36
+ def expire(*tags)
37
+ return unless perform_caching?
38
+
39
+ # delete them from the cache
40
+ tags.each do |tag|
41
+ if fragment_keys = Rails.cache.fetch(tag)
42
+ fragment_keys.each do |fragment_key|
43
+ Rails.cache.delete(fragment_key)
44
+ end
45
+ end
46
+
47
+ Rails.cache.delete(tag)
48
+ end
49
+
50
+ # now remove them from the list
51
+ # of stored tags
52
+ remove_tags_from_tag_list(tags)
53
+ end
54
+
55
+ def tags
56
+ Rails.cache.fetch(CACHE_KEY) || []
57
+ end
58
+
59
+ def clear
60
+ expire(*tags)
61
+ Rails.cache.delete(CACHE_KEY)
62
+ end
63
+
64
+ def wipe
65
+ clear
66
+ end
67
+
68
+ def keys
69
+ tags.inject([]) do |arry, tag|
70
+ arry += (Rails.cache.fetch(tag) || [])
71
+ end.compact
72
+ end
73
+
74
+ def keys_for(tag)
75
+ Rails.cache.fetch(tag) || []
76
+ end
77
+
78
+ private
79
+ def add_tags_to_tag_list(*tags)
80
+ cachier_tags = get_cachier_tags
81
+
82
+ cachier_tags = (cachier_tags + tags).uniq
83
+ write_cachier_tags(cachier_tags)
84
+ end
85
+
86
+ def write_cachier_tags(cachier_tags)
87
+ Rails.cache.write(CACHE_KEY, cachier_tags)
88
+ end
89
+
90
+ def remove_tags_from_tag_list(*tags)
91
+ cachier_tags = get_cachier_tags
92
+
93
+ cachier_tags = (cachier_tags - tags).uniq
94
+ write_cachier_tags(cachier_tags)
95
+ end
96
+
97
+ def get_cachier_tags
98
+ cachier_tags = Rails.cache.fetch(CACHE_KEY) || []
99
+ cachier_tags
100
+ end
101
+ end
102
+
103
+ require 'cachier/controller_helper'
104
+ require 'cachier/matchers'
@@ -0,0 +1,34 @@
1
+ # Hooks into ApplicationController's write_fragment method.
2
+ # write_fragment is used for action and fragment caching.
3
+ # Create an alias method chain to call our customer method
4
+ # which stores the associated key with the tag in a
5
+ # Redis Set. Then we can expire all those keys from anywhere
6
+ # in the code using Rails.cache.delete
7
+ #
8
+ # I use alias_method_chain instead of calling 'super'
9
+ # because there is a very rare case where someone
10
+ # may have redfined 'write_fragment' in their own
11
+ # controllers. Using an alias method chain
12
+ # keeps those methods intact.
13
+
14
+ module Cachier
15
+ module ControllerHelper
16
+ def self.included(klass)
17
+ klass.class_eval do
18
+ def write_fragment_with_tagged_key(key, content, options = nil)
19
+ if options && options[:tag] && Cachier.perform_caching?
20
+ tags = case options[:tag].class.to_s
21
+ when 'Proc', 'Lambda'
22
+ options[:tag].call(self)
23
+ else
24
+ options[:tag]
25
+ end
26
+ Cachier.store_fragment fragment_cache_key(key), *tags
27
+ end
28
+ write_fragment_without_tagged_key(key, content, options)
29
+ end
30
+ alias_method_chain :write_fragment, :tagged_key
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ World(Cachier::Matchers)
2
+
3
+ Before('@caching') do
4
+ Cachier.clear
5
+ Rails.cache.clear
6
+ end
@@ -0,0 +1,39 @@
1
+ module Cachier
2
+ module Matchers
3
+
4
+ def be_cached
5
+ Cache.new
6
+ end
7
+
8
+ class Cache
9
+ def matches?(target)
10
+ @target = target
11
+
12
+ @test_results = Cachier.keys_for(@target).inject({}) do |hash, key|
13
+ hash.merge(key => Rails.cache.exist?(key))
14
+ end
15
+
16
+ flag = @test_results.values.inject(true) { |f, v| f && v }
17
+ flag && Cachier.keys_for(@target).present?
18
+ end
19
+
20
+ def failure_message_for_should
21
+ <<-msg
22
+ expected the Rails.cache to include all these keys:
23
+ #{Cachier.keys_for(@target).to_sentence}, but
24
+ it did not include these keys:
25
+ #{@test_results.keys.select {|k| @test_results[k] == false }.to_sentence}
26
+ msg
27
+ end
28
+
29
+ def failure_message_for_should_not
30
+ <<-msg
31
+ expected the Rails.cache to not include all these keys:
32
+ #{Cachier.keys_for(@target).to_sentence}, but
33
+ it did include these keys:
34
+ #{@test_results.keys.select {|k| @test_results[k] == true }.to_sentence}
35
+ msg
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module Cachier
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,34 @@
1
+ # Hooks into ApplicationController's write_fragment method.
2
+ # write_fragment is used for action and fragment caching.
3
+ # Create an alias method chain to call our customer method
4
+ # which stores the associated key with the tag in a
5
+ # Redis Set. Then we can expire all those keys from anywhere
6
+ # in the code using Rails.cache.delete
7
+ #
8
+ # I use alias_method_chain instead of calling 'super'
9
+ # because there is a very rare case where someone
10
+ # may have redfined 'write_fragment' in their own
11
+ # controllers. Using an alias method chain
12
+ # keeps those methods intact.
13
+
14
+ module Cashier
15
+ module ControllerHelper
16
+ def self.included(klass)
17
+ klass.class_eval do
18
+ def write_fragment_with_tagged_key(key, content, options = nil)
19
+ if options && options[:tag] && Cashier.perform_caching?
20
+ tags = case options[:tag].class.to_s
21
+ when 'Proc', 'Lambda'
22
+ options[:tag].call(self)
23
+ else
24
+ options[:tag]
25
+ end
26
+ Cashier.store_fragment fragment_cache_key(key), *tags
27
+ end
28
+ write_fragment_without_tagged_key(key, content, options)
29
+ end
30
+ alias_method_chain :write_fragment, :tagged_key
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ World(Cashier::Matchers)
2
+
3
+ Before('@caching') do
4
+ Cashier.clear
5
+ Rails.cache.clear
6
+ end
@@ -0,0 +1,39 @@
1
+ module Cashier
2
+ module Matchers
3
+
4
+ def be_cached
5
+ Cache.new
6
+ end
7
+
8
+ class Cache
9
+ def matches?(target)
10
+ @target = target
11
+
12
+ @test_results = Cashier.keys_for(@target).inject({}) do |hash, key|
13
+ hash.merge(key => Rails.cache.exist?(key))
14
+ end
15
+
16
+ flag = @test_results.values.inject(true) { |f, v| f && v }
17
+ flag && Cashier.keys_for(@target).present?
18
+ end
19
+
20
+ def failure_message_for_should
21
+ <<-msg
22
+ expected the Rails.cache to include all these keys:
23
+ #{Cashier.keys_for(@target).to_sentence}, but
24
+ it did not include these keys:
25
+ #{@test_results.keys.select {|k| @test_results[k] == false }.to_sentence}
26
+ msg
27
+ end
28
+
29
+ def failure_message_for_should_not
30
+ <<-msg
31
+ expected the Rails.cache to not include all these keys:
32
+ #{Cashier.keys_for(@target).to_sentence}, but
33
+ it did include these keys:
34
+ #{@test_results.keys.select {|k| @test_results[k] == true }.to_sentence}
35
+ msg
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,8 @@
1
+ module Cashier
2
+ class Railtie < Rails::Railtie
3
+ initializer 'cashier.initialize' do
4
+ ApplicationController.send :include, Cashier::ControllerHelper
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,3 @@
1
+ module Cashier
2
+ VERSION = "0.2.0"
3
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cachier
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Avi Tzurel
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-10-19 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: hiredis
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: redis
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: redis-namespace
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :development
76
+ version_requirements: *id004
77
+ description: Tag your cache keys smartly, you can expire by tags, count keys per tag and many more. based on Redis
78
+ email: avi@kensodev.com
79
+ executables: []
80
+
81
+ extensions: []
82
+
83
+ extra_rdoc_files: []
84
+
85
+ files:
86
+ - lib/cachier/controller_helper.rb
87
+ - lib/cachier/cucumber.rb
88
+ - lib/cachier/matchers.rb
89
+ - lib/cachier/version.rb
90
+ - lib/cachier.rb
91
+ - lib/controller_helper.rb
92
+ - lib/cucumber.rb
93
+ - lib/matchers.rb
94
+ - lib/railtie.rb
95
+ - lib/version.rb
96
+ has_rdoc: true
97
+ homepage: https://github.com/KensoDev/cachier
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options: []
102
+
103
+ require_paths:
104
+ - .
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ requirements: []
124
+
125
+ rubyforge_project:
126
+ rubygems_version: 1.3.7
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: Tagging ability for your cache keys, based on Redis
130
+ test_files: []
131
+