taggable_cache 0.3.0 → 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/.gitignore CHANGED
@@ -15,3 +15,5 @@ pkg
15
15
  /spec/internal/log
16
16
  /spec/internal/db/*.sqlite
17
17
  /tmp
18
+
19
+ /Gemfile.lock
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
- lang: ruby
1
+ language: ruby
2
2
  bundler_args: --without development
3
3
  before_install:
4
4
  - gem install bundler --pre
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ = Taggable cache 0.4.0
2
+
3
+ - Rewriten rails integration
4
+ - Added README
5
+ - Fix warnings
6
+ - Redis configuration variables can be set by environment variables
data/README.rdoc CHANGED
@@ -1,10 +1,42 @@
1
1
  = Taggable cache
2
2
 
3
- This gem simplifies cache expiration in rails.
3
+ This gem simplifies cache expiration in rails by adding depends_on helper, which expires cache element when depending object is changed/deleted.
4
4
 
5
5
  = How to use
6
6
 
7
- See example in spec/internal.
7
+ Controller(action caching):
8
+
9
+ caches_action :index
10
+
11
+ def index
12
+ Page.load_lot_of_data
13
+
14
+ #this depends on any Page object change - creation, deletion, change
15
+ depends_on Page
16
+ end
17
+
18
+ View(fragment caching):
19
+
20
+ <%# Page.active can be AR scope, every Page object on change is checked if it is in this scope, and if is - expires cache element %>
21
+ <% cache 'cache_entry', :depends_on => [Page.active] do %>
22
+ <% Page.load_lot_of_data %>
23
+ <% end %>
24
+
25
+ Usage with Rails.cache:
26
+
27
+ page = Page.first
28
+ #this cache key expires only if this Page object is changed/deleted
29
+ Rails.cache.write('key', 'value', :depends_on => [page])
30
+
31
+ Usage with cells gem:
32
+
33
+ class TabsCell < Cell::Rails
34
+ cache :index, nil, :depends_on => [Category, Metacategory, Product]
35
+
36
+ def index
37
+ render
38
+ end
39
+ end
8
40
 
9
41
  == Build Status {<img src="https://secure.travis-ci.org/brain-geek/taggable-cache.png"/>}[http://travis-ci.org/brain-geek/taggable-cache]
10
42
 
@@ -1,3 +1,5 @@
1
+ require 'rails'
2
+
1
3
  module TaggableCache
2
4
  end
3
5
 
@@ -0,0 +1,92 @@
1
+ module TaggableCache
2
+ module CacheStoreExtension
3
+ extend ActiveSupport::Concern
4
+ def self.included(base)
5
+ base.class_eval do
6
+ def taggable
7
+ @taggable ||= ::TaggableCache::Store.new
8
+ end
9
+
10
+ alias_method :original_write, :write
11
+
12
+ def write(name, value, options = nil)
13
+ if !options.nil? && options.has_key?(:depends_on)
14
+ add_tags(name, *options[:depends_on])
15
+ end
16
+
17
+ original_write(name, value, options)
18
+ end
19
+
20
+ def add_tags(key, *params)
21
+ taggable.add(key, *params)
22
+ end
23
+
24
+ def delete_by_tags(*params)
25
+ taggable.get(*params).each do |m|
26
+ self.delete(m)
27
+ end
28
+
29
+ taggable.get_scope(*(params.delete_if{|a| not a.is_a? ActiveRecord::Base})).each do |m|
30
+ self.delete(m)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ module ActionControllerExtension
38
+ extend ActiveSupport::Concern
39
+ def self.included(base)
40
+ base.class_eval do
41
+ def depends_on(*keys)
42
+ _process_action_callbacks.find_all{|x|
43
+ (x.kind == :around) &&
44
+ (x.raw_filter.is_a? ActionController::Caching::Actions::ActionCacheFilter) }.each do |callback|
45
+ cache_path = callback.raw_filter.instance_variable_get('@cache_path')
46
+
47
+ path_options = if cache_path.respond_to?(:call)
48
+ instance_exec(self, &cache_path)
49
+ else
50
+ cache_path
51
+ end
52
+
53
+ path_options = ::ActionController::Caching::Actions::ActionCachePath.new(self, path_options || {}).path
54
+
55
+ Rails.cache.add_tags(fragment_cache_key(path_options), *keys)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ module ActiveRecordExtension
63
+ extend ActiveSupport::Concern
64
+ included do
65
+ # Future subclasses will pick up the model extension
66
+ class << self
67
+ def inherited_with_taggable(kls)
68
+ inherited_without_taggable kls
69
+ kls.send(:include, TaggableCache::ActiveRecordModelExtension) if kls.superclass == ActiveRecord::Base
70
+ end
71
+ alias_method_chain :inherited, :taggable
72
+ end
73
+
74
+ # Existing subclasses pick up the model extension as well
75
+ self.descendants.each do |kls|
76
+ kls.send(:include, TaggableCache::ActiveRecordModelExtension) if kls.superclass == ActiveRecord::Base
77
+ end
78
+ end
79
+ end
80
+
81
+
82
+ module ActiveRecordModelExtension
83
+ extend ActiveSupport::Concern
84
+ def self.included(base)
85
+ [:after_update, :before_update, :before_destroy, :after_create].each do |event|
86
+ base.send(event, Proc.new do |model|
87
+ Rails.cache.delete_by_tags(model, model.class)
88
+ end)
89
+ end
90
+ end
91
+ end
92
+ end
@@ -1,51 +1,13 @@
1
- require 'active_record'
2
- require 'action_controller'
3
- require 'rails'
4
-
5
- require 'taggable_cache/spectator'
6
-
7
- ActiveSupport::Cache::Store.class_eval do
8
- def taggable
9
- @taggable ||= ::TaggableCache::Store.new
10
- end
11
-
12
- alias_method :original_write, :write
13
-
14
- def write(name, value, options = nil)
15
- if !options.nil? && options.has_key?(:depends_on)
16
- add_tags(name, *options[:depends_on])
17
- end
18
-
19
- original_write(name, value, options)
20
- end
21
-
22
- def add_tags(key, *params)
23
- taggable.add(key, *params)
24
- end
25
-
26
- def delete_by_tags(*params)
27
- taggable.get(*params).each do |m|
28
- self.delete(m)
29
- end
30
-
31
- taggable.get_scope(*(params.delete_if{|a| not a.is_a? ActiveRecord::Base})).each do |m|
32
- self.delete(m)
33
- end
34
- end
35
- end
36
-
37
- ActionController::Base.class_eval do
38
- def depends_on(*params)
39
- key_name = fragment_cache_key(::ActionController::Caching::Actions::ActionCachePath.new(self).path)
40
- Rails.cache.add_tags(key_name, *params)
41
- end
42
- end
1
+ require 'taggable_cache/extensions'
43
2
 
44
3
  module TaggableCache
45
4
  class Railtie < ::Rails::Railtie
46
5
  initializer "taggable_cache" do |app|
47
- ActiveRecord::Base.observers << TaggableCache::Spectator
48
- ActiveRecord::Base.add_observer TaggableCache::Spectator.instance
49
- end
6
+ ActiveSupport.on_load(:active_record) do
7
+ ::ActiveRecord::Base.send :include, TaggableCache::ActiveRecordExtension
8
+ ::ActiveSupport::Cache::Store.send :include, TaggableCache::CacheStoreExtension
9
+ ::ActionController::Base.send :include, TaggableCache::ActionControllerExtension
10
+ end
11
+ end
50
12
  end
51
13
  end
@@ -3,7 +3,8 @@ require "digest/md5"
3
3
 
4
4
  class TaggableCache::Store
5
5
  def initialize
6
- @redis = Redis.new
6
+ @redis = Redis.new :host => ENV['REDIS_HOST'] || '127.0.0.1',
7
+ :port => ENV['REDIS_PORT'] ? ENV['REDIS_PORT'].to_i : 6379
7
8
  end
8
9
 
9
10
  def id_for(obj)
@@ -1,3 +1,3 @@
1
1
  module TaggableCache
2
- VERSION = "0.3.0" # This is for the gem and does not conflict with the rest of the functionality
2
+ VERSION = "0.4.0" # This is for the gem and does not conflict with the rest of the functionality
3
3
  end
@@ -1,15 +1,21 @@
1
1
  class ActionCachingController < ActionController::Base
2
2
  caches_action :index
3
3
 
4
+ caches_action :cp, :cache_path => Proc.new { {'key' => 'value', 2 => 56} }
5
+
4
6
  def index
5
7
  Page.load_lot_of_data
6
8
 
7
9
  depends_on Page
8
10
 
9
- render :text => 'sdfsd'
11
+ render :text => 'none'
10
12
  end
11
13
 
12
- def expire
13
- expire_action :action => :index
14
+ def cp
15
+ Page.load_lot_of_data
16
+
17
+ depends_on Page
18
+
19
+ render :text => 'none'
14
20
  end
15
21
  end
@@ -1,28 +1,59 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActionCachingController do
4
- before :each do
5
- get 'action_caching/expire'
6
- @url = 'action_caching/index'
7
- end
4
+ describe "simple" do
5
+ before :each do
6
+ Rails.cache.clear
7
+ Redis.new.flushall
8
+ @url = 'action_caching/index'
9
+ end
10
+
11
+ it "should be successful" do
12
+ Page.should_receive :load_lot_of_data
13
+ get @url
14
+ response.status.should be(200)
15
+ end
16
+
17
+ it "should run second test with cache deletion" do
18
+ Page.should_receive(:load_lot_of_data).once
19
+ get @url
20
+ response.status.should be(200)
8
21
 
9
- it "should be successful" do
10
- Page.should_receive :load_lot_of_data
11
- get @url
12
- response.status.should be(200)
22
+ get @url
23
+ response.status.should be(200)
24
+
25
+ Page.should_receive(:load_lot_of_data).once
26
+ Page.create
27
+ get @url
28
+ response.status.should be(200)
29
+ end
13
30
  end
14
31
 
15
- it "should run second test without cache" do
16
- Page.should_receive(:load_lot_of_data).once
17
- get @url
18
- response.status.should be(200)
32
+ describe "with cache_path" do
33
+ before :each do
34
+ Rails.cache.clear
35
+ Redis.new.flushall
36
+ @url = 'action_caching/cp'
37
+ end
38
+
39
+ it "should be successful" do
40
+ Page.should_receive :load_lot_of_data
41
+ get @url
42
+ response.status.should be(200)
43
+ end
44
+
45
+ it "should run second test with cache deletion" do
46
+ Page.should_receive(:load_lot_of_data).once
47
+ get @url
48
+ response.status.should be(200)
19
49
 
20
- get @url
21
- response.status.should be(200)
50
+ get @url
51
+ response.status.should be(200)
22
52
 
23
- Page.should_receive(:load_lot_of_data).once
24
- Page.create
25
- get @url
26
- response.status.should be(200)
53
+ Page.should_receive(:load_lot_of_data).once
54
+ Page.create
55
+ get @url
56
+ response.status.should be(200)
57
+ end
27
58
  end
28
59
  end
@@ -0,0 +1,23 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
2
+
3
+ describe TaggableCache::Store do
4
+ after :all do
5
+ ENV.delete("REDIS_HOST")
6
+ ENV.delete("REDIS_PORT")
7
+ end
8
+
9
+ it "should fall back to defaults if no settings given" do
10
+ Redis.should_receive(:new).with(:host => '127.0.0.1', :port => 6379)
11
+
12
+ TaggableCache::Store.new
13
+ end
14
+
15
+ it "should use ENV settings" do
16
+ ENV["REDIS_HOST"] = 'hostname.lvh.me';
17
+ ENV["REDIS_PORT"] = '1234';
18
+
19
+ Redis.should_receive(:new).with(:host => 'hostname.lvh.me', :port => 1234)
20
+
21
+ TaggableCache::Store.new
22
+ end
23
+ end
@@ -28,7 +28,10 @@ Gem::Specification.new do |s|
28
28
  s.rubygems_version = "1.8.15"
29
29
  s.summary = "This gem simplifies cache expiration in rails by providing depends_on option to rails cache."
30
30
 
31
- s.add_dependency(%q<rails>, [">= 3.1.0"])
31
+ #s.add_dependency(%q<rails>, [">= 3.1.0"])
32
+ s.add_dependency(%q<railties>, [">= 3.1.0"])
33
+ s.add_dependency(%q<actionpack>, [">= 3.1.0"])
34
+ s.add_dependency(%q<activerecord>, [">= 3.1.0"])
32
35
  s.add_dependency(%q<redis>, [">= 2.2.2"])
33
36
  end
34
37
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taggable_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,8 +12,8 @@ cert_chain: []
12
12
  date: 2012-02-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: rails
16
- requirement: &71322420 !ruby/object:Gem::Requirement
15
+ name: railties
16
+ requirement: &77251570 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,32 @@ dependencies:
21
21
  version: 3.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *71322420
24
+ version_requirements: *77251570
25
+ - !ruby/object:Gem::Dependency
26
+ name: actionpack
27
+ requirement: &77251040 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 3.1.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *77251040
36
+ - !ruby/object:Gem::Dependency
37
+ name: activerecord
38
+ requirement: &77250480 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 3.1.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *77250480
25
47
  - !ruby/object:Gem::Dependency
26
48
  name: redis
27
- requirement: &71321470 !ruby/object:Gem::Requirement
49
+ requirement: &77249530 !ruby/object:Gem::Requirement
28
50
  none: false
29
51
  requirements:
30
52
  - - ! '>='
@@ -32,7 +54,7 @@ dependencies:
32
54
  version: 2.2.2
33
55
  type: :runtime
34
56
  prerelease: false
35
- version_requirements: *71321470
57
+ version_requirements: *77249530
36
58
  description: This gem simplifies cache expiration in rails
37
59
  email: brain-geek@yandex.ua
38
60
  executables: []
@@ -43,17 +65,16 @@ extra_rdoc_files:
43
65
  files:
44
66
  - .gitignore
45
67
  - .travis.yml
68
+ - CHANGELOG.md
46
69
  - Gemfile
47
- - Gemfile.lock
48
70
  - LICENSE.txt
49
71
  - README.rdoc
50
72
  - Rakefile
51
73
  - gemfiles/Gemfile-rails.3.1.x
52
74
  - gemfiles/Gemfile-rails.3.2.x
53
75
  - lib/taggable_cache.rb
54
- - lib/taggable_cache/dynamic_store.rb
76
+ - lib/taggable_cache/extensions.rb
55
77
  - lib/taggable_cache/railtie.rb
56
- - lib/taggable_cache/spectator.rb
57
78
  - lib/taggable_cache/store.rb
58
79
  - lib/taggable_cache/version.rb
59
80
  - spec/integration/rails_cache_spec.rb
@@ -64,10 +85,10 @@ files:
64
85
  - spec/internal/config/database.yml
65
86
  - spec/internal/config/routes.rb
66
87
  - spec/internal/db/schema.rb
67
- - spec/internal/public/favicon.ico
68
88
  - spec/requests/action_caching_controller_spec.rb
69
89
  - spec/requests/fragment_caching_controller_spec.rb
70
90
  - spec/spec_helper.rb
91
+ - spec/taggable-cache/settings_spec.rb
71
92
  - spec/taggable-cache/store_spec.rb
72
93
  - taggable-cache.gemspec
73
94
  homepage: http://github.com/brain-geek/taggable-cache
@@ -85,7 +106,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
106
  version: '0'
86
107
  segments:
87
108
  - 0
88
- hash: -516926623
109
+ hash: 1067828559
89
110
  required_rubygems_version: !ruby/object:Gem::Requirement
90
111
  none: false
91
112
  requirements:
@@ -94,10 +115,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
115
  version: '0'
95
116
  segments:
96
117
  - 0
97
- hash: -516926623
118
+ hash: 1067828559
98
119
  requirements: []
99
120
  rubyforge_project:
100
- rubygems_version: 1.8.17
121
+ rubygems_version: 1.8.10
101
122
  signing_key:
102
123
  specification_version: 3
103
124
  summary: This gem simplifies cache expiration in rails by providing depends_on option
data/Gemfile.lock DELETED
@@ -1,148 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- taggable_cache (0.3.0)
5
- rails (>= 3.1.0)
6
- redis (>= 2.2.2)
7
-
8
- GEM
9
- remote: http://rubygems.org/
10
- specs:
11
- actionmailer (3.2.2)
12
- actionpack (= 3.2.2)
13
- mail (~> 2.4.0)
14
- actionpack (3.2.2)
15
- activemodel (= 3.2.2)
16
- activesupport (= 3.2.2)
17
- builder (~> 3.0.0)
18
- erubis (~> 2.7.0)
19
- journey (~> 1.0.1)
20
- rack (~> 1.4.0)
21
- rack-cache (~> 1.1)
22
- rack-test (~> 0.6.1)
23
- sprockets (~> 2.1.2)
24
- activemodel (3.2.2)
25
- activesupport (= 3.2.2)
26
- builder (~> 3.0.0)
27
- activerecord (3.2.2)
28
- activemodel (= 3.2.2)
29
- activesupport (= 3.2.2)
30
- arel (~> 3.0.2)
31
- tzinfo (~> 0.3.29)
32
- activeresource (3.2.2)
33
- activemodel (= 3.2.2)
34
- activesupport (= 3.2.2)
35
- activesupport (3.2.2)
36
- i18n (~> 0.6)
37
- multi_json (~> 1.0)
38
- arel (3.0.2)
39
- builder (3.0.0)
40
- capybara (1.1.2)
41
- mime-types (>= 1.16)
42
- nokogiri (>= 1.3.3)
43
- rack (>= 1.0.0)
44
- rack-test (>= 0.5.4)
45
- selenium-webdriver (~> 2.0)
46
- xpath (~> 0.1.4)
47
- childprocess (0.3.1)
48
- ffi (~> 1.0.6)
49
- coderay (1.0.5)
50
- combustion (0.3.2)
51
- rails (>= 3.0.0)
52
- thor (>= 0.14.6)
53
- diff-lcs (1.1.3)
54
- erubis (2.7.0)
55
- ffi (1.0.11)
56
- hike (1.2.1)
57
- i18n (0.6.0)
58
- journey (1.0.3)
59
- json (1.6.5)
60
- mail (2.4.3)
61
- i18n (>= 0.4.0)
62
- mime-types (~> 1.16)
63
- treetop (~> 1.4.8)
64
- method_source (0.7.1)
65
- mime-types (1.17.2)
66
- multi_json (1.1.0)
67
- nokogiri (1.5.0)
68
- polyglot (0.3.3)
69
- pry (0.9.8.4)
70
- coderay (~> 1.0.5)
71
- method_source (~> 0.7.1)
72
- slop (>= 2.4.4, < 3)
73
- pry-nav (0.1.0)
74
- pry (~> 0.9.8.1)
75
- rack (1.4.1)
76
- rack-cache (1.2)
77
- rack (>= 0.4)
78
- rack-ssl (1.3.2)
79
- rack
80
- rack-test (0.6.1)
81
- rack (>= 1.0)
82
- rails (3.2.2)
83
- actionmailer (= 3.2.2)
84
- actionpack (= 3.2.2)
85
- activerecord (= 3.2.2)
86
- activeresource (= 3.2.2)
87
- activesupport (= 3.2.2)
88
- bundler (~> 1.0)
89
- railties (= 3.2.2)
90
- railties (3.2.2)
91
- actionpack (= 3.2.2)
92
- activesupport (= 3.2.2)
93
- rack-ssl (~> 1.3.2)
94
- rake (>= 0.8.7)
95
- rdoc (~> 3.4)
96
- thor (~> 0.14.6)
97
- rake (0.9.2.2)
98
- rdoc (3.12)
99
- json (~> 1.4)
100
- redis (2.2.2)
101
- rspec (2.8.0)
102
- rspec-core (~> 2.8.0)
103
- rspec-expectations (~> 2.8.0)
104
- rspec-mocks (~> 2.8.0)
105
- rspec-core (2.8.0)
106
- rspec-expectations (2.8.0)
107
- diff-lcs (~> 1.1.2)
108
- rspec-mocks (2.8.0)
109
- rspec-rails (2.8.1)
110
- actionpack (>= 3.0)
111
- activesupport (>= 3.0)
112
- railties (>= 3.0)
113
- rspec (~> 2.8.0)
114
- rubyzip (0.9.6.1)
115
- selenium-webdriver (2.20.0)
116
- childprocess (>= 0.2.5)
117
- ffi (~> 1.0)
118
- multi_json (~> 1.0)
119
- rubyzip
120
- slop (2.4.4)
121
- sprockets (2.1.2)
122
- hike (~> 1.2)
123
- rack (~> 1.0)
124
- tilt (~> 1.1, != 1.3.0)
125
- sqlite3 (1.3.5)
126
- thor (0.14.6)
127
- tilt (1.3.3)
128
- treetop (1.4.10)
129
- polyglot
130
- polyglot (>= 0.3.1)
131
- tzinfo (0.3.32)
132
- xpath (0.1.4)
133
- nokogiri (~> 1.3)
134
-
135
- PLATFORMS
136
- ruby
137
-
138
- DEPENDENCIES
139
- capybara
140
- combustion
141
- pry
142
- pry-nav
143
- rails (~> 3.2.0)
144
- rake
145
- rspec
146
- rspec-rails
147
- sqlite3
148
- taggable_cache!
@@ -1,5 +0,0 @@
1
- require "redis"
2
-
3
- class TaggableCache::DynamicStore < TaggableCache::Store
4
-
5
- end
@@ -1,10 +0,0 @@
1
- class TaggableCache::Spectator < ActiveRecord::Observer
2
- def event(model)
3
- Rails.cache.delete_by_tags(model, model.class)
4
- end
5
-
6
- alias :after_update :event
7
- alias :before_update :event
8
- alias :before_destroy :event
9
- alias :after_create :event
10
- end
File without changes