taggable_cache 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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