cachier 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.
@@ -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
+