taggable_cache 0.4.1 → 0.4.2
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/.rvmrc +1 -0
- data/.travis.yml +1 -6
- data/CHANGELOG.md +5 -0
- data/README.rdoc +9 -1
- data/gemfiles/Gemfile-rails.3.1.x +1 -1
- data/gemfiles/Gemfile.shared +1 -1
- data/lib/taggable_cache/extensions/action_controller.rb +26 -0
- data/lib/taggable_cache/extensions/active_record.rb +32 -0
- data/lib/taggable_cache/extensions/cache_store.rb +56 -0
- data/lib/taggable_cache/railtie.rb +3 -1
- data/lib/taggable_cache/store/base.rb +59 -0
- data/lib/taggable_cache/store/redis.rb +55 -0
- data/lib/taggable_cache/store.rb +2 -85
- data/lib/taggable_cache/version.rb +1 -1
- data/spec/integration/rails_cache_spec.rb +1 -1
- data/spec/taggable-cache/expire_all_spec.rb +39 -0
- data/spec/taggable-cache/settings_spec.rb +2 -2
- data/spec/taggable-cache/store_spec.rb +20 -7
- data/taggable-cache.gemspec +2 -3
- metadata +42 -17
- data/lib/taggable_cache/extensions.rb +0 -92
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3-falcon
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.rdoc
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
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
|
+
= Build Status {<img src="https://secure.travis-ci.org/brain-geek/taggable-cache.png"/>}[http://travis-ci.org/brain-geek/taggable-cache]
|
5
6
|
= How to use
|
7
|
+
For taggable-cache you must have redis server for data about tags. Cache storage can be anything, but gem uses redis for its own storage.
|
6
8
|
|
7
9
|
Controller(action caching):
|
8
10
|
|
@@ -38,7 +40,13 @@ Usage with cells gem:
|
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
|
43
|
+
If you are using redis for cache, it is recommended to set default expire_ttl value:
|
44
|
+
|
45
|
+
config.cache_store = ActiveSupport::Cache::RedisStore.new(:expire_in => 16.hours.to_i)
|
46
|
+
|
47
|
+
== What is supported
|
48
|
+
|
49
|
+
Rails 3.1.x and 3.2.x are supported. Tested with ruby 1.9.3, but should work on 1.8.7. As cache storage you can use redis, memcached and file store caches.
|
42
50
|
|
43
51
|
== Contributing to taggable-cache
|
44
52
|
|
data/gemfiles/Gemfile.shared
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
module TaggableCache
|
2
|
+
module ActionControllerExtension
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
def depends_on(*keys)
|
7
|
+
_process_action_callbacks.find_all{|x|
|
8
|
+
(x.kind == :around) &&
|
9
|
+
(x.raw_filter.is_a? ActionController::Caching::Actions::ActionCacheFilter) }.each do |callback|
|
10
|
+
cache_path = callback.raw_filter.instance_variable_get('@cache_path')
|
11
|
+
|
12
|
+
path_options = if cache_path.respond_to?(:call)
|
13
|
+
instance_exec(self, &cache_path)
|
14
|
+
else
|
15
|
+
cache_path
|
16
|
+
end
|
17
|
+
|
18
|
+
path_options = ::ActionController::Caching::Actions::ActionCachePath.new(self, path_options || {}).path
|
19
|
+
|
20
|
+
Rails.cache.add_tags(fragment_cache_key(path_options), *keys)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module TaggableCache
|
2
|
+
module ActiveRecordExtension
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
# Future subclasses will pick up the model extension
|
6
|
+
class << self
|
7
|
+
def inherited_with_taggable(kls)
|
8
|
+
inherited_without_taggable kls
|
9
|
+
kls.send(:include, TaggableCache::ActiveRecordModelExtension) if kls.superclass == ActiveRecord::Base
|
10
|
+
end
|
11
|
+
alias_method_chain :inherited, :taggable
|
12
|
+
end
|
13
|
+
|
14
|
+
# Existing subclasses pick up the model extension as well
|
15
|
+
self.descendants.each do |kls|
|
16
|
+
kls.send(:include, TaggableCache::ActiveRecordModelExtension) if kls.superclass == ActiveRecord::Base
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
module ActiveRecordModelExtension
|
23
|
+
extend ActiveSupport::Concern
|
24
|
+
def self.included(base)
|
25
|
+
[:after_update, :before_update, :before_destroy, :after_create].each do |event|
|
26
|
+
base.send(event, Proc.new do |model|
|
27
|
+
Rails.cache.delete_by_tags(model, model.class)
|
28
|
+
end)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,56 @@
|
|
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::Redis.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_with_taggable(name, value, options = nil)
|
11
|
+
if !options.nil? && options.has_key?(:depends_on)
|
12
|
+
add_tags(name, *options[:depends_on])
|
13
|
+
end
|
14
|
+
|
15
|
+
write_without_taggable(name, value, options)
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method_chain :write, :taggable
|
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
|
+
|
34
|
+
def expire_all
|
35
|
+
#Load all the models
|
36
|
+
Dir.glob(Rails.root + '/app/models/*.rb').each {|file| require file}
|
37
|
+
|
38
|
+
ActiveRecord::Base.subclasses.each do |cls|
|
39
|
+
delete_by_tags cls
|
40
|
+
|
41
|
+
pk_name = cls.primary_key
|
42
|
+
|
43
|
+
return if cls.unscoped.first.nil? #There is no sence in continuing, if model is empty
|
44
|
+
|
45
|
+
last_id = cls.order(pk_name).last.try(pk_name.to_sym)
|
46
|
+
first_id = 1
|
47
|
+
|
48
|
+
(first_id..last_id).each do |id|
|
49
|
+
delete_by_tags({:cls => cls, :id => id})
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module TaggableCache::Store
|
2
|
+
class Base
|
3
|
+
def id_for(obj)
|
4
|
+
if obj.is_a? Class
|
5
|
+
obj.to_s.downcase
|
6
|
+
elsif obj.is_a? ActiveRecord::Base
|
7
|
+
if obj.persisted?
|
8
|
+
"#{obj.class.to_s.downcase}-#{obj.id}"
|
9
|
+
else
|
10
|
+
id_for(obj.class)
|
11
|
+
end
|
12
|
+
elsif obj.is_a? Arel::SelectManager
|
13
|
+
"query-keys-#{Digest::MD5.hexdigest(obj.to_sql)}"
|
14
|
+
elsif obj.is_a? ActiveRecord::Relation
|
15
|
+
id_for(obj.arel)
|
16
|
+
elsif obj.is_a? Hash
|
17
|
+
if obj.include?(:cls) && obj.include?(:id)
|
18
|
+
"#{obj[:cls].to_s.downcase}-#{obj[:id]}"
|
19
|
+
else
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
else
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def is_scope?(scope)
|
28
|
+
(scope.is_a? ActiveRecord::Relation) || (scope.is_a? Arel::SelectManager)
|
29
|
+
end
|
30
|
+
|
31
|
+
def in_scope?(scope, object)
|
32
|
+
return false unless object.persisted?
|
33
|
+
|
34
|
+
query = scope.where(scope.froms.first[:id].eq(object.id)).to_sql
|
35
|
+
|
36
|
+
object.class.connection.select_all(query).length > 0
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
raise ActionController::NotImplemented.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def add(tag, *members)
|
44
|
+
raise ActionController::NotImplemented.new
|
45
|
+
end
|
46
|
+
|
47
|
+
def get(*members)
|
48
|
+
raise ActionController::NotImplemented.new
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_scope(tag, scope)
|
52
|
+
raise ActionController::NotImplemented.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_scope(*members)
|
56
|
+
raise ActionController::NotImplemented.new
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "redis"
|
2
|
+
require "digest/md5"
|
3
|
+
|
4
|
+
module TaggableCache::Store
|
5
|
+
class Redis < TaggableCache::Store::Base
|
6
|
+
def initialize
|
7
|
+
@redis = ::Redis.new :host => ENV['REDIS_HOST'] || '127.0.0.1',
|
8
|
+
:port => ENV['REDIS_PORT'] ? ENV['REDIS_PORT'].to_i : 6379
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(tag, *members)
|
12
|
+
members.each do |element|
|
13
|
+
add_scope(tag, element) if is_scope? element
|
14
|
+
ident = id_for(element)
|
15
|
+
@redis.sadd ident, tag unless ident.nil?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(*members)
|
20
|
+
keys = members.map { |tag| id_for(tag) }
|
21
|
+
elements = @redis.sunion(keys)
|
22
|
+
@redis.del(keys)
|
23
|
+
elements.flatten.compact
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_scope(tag, scope)
|
27
|
+
scope = scope.arel if scope.is_a? ActiveRecord::Relation
|
28
|
+
table_name = scope.froms.first.name
|
29
|
+
query_fingerprint = Digest::MD5.hexdigest(scope.to_sql)
|
30
|
+
|
31
|
+
@redis.sadd "#{table_name}-scopes", "#{query_fingerprint}"
|
32
|
+
@redis.set "query-#{query_fingerprint}", Marshal.dump(scope)
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_scope(*members)
|
36
|
+
keys = members.delete_if{|a| not a.is_a? ActiveRecord::Base }.map do |object|
|
37
|
+
|
38
|
+
table_redis_key = "#{object.class.table_name}-scopes"
|
39
|
+
|
40
|
+
@redis.smembers(table_redis_key).map do |scope_key|
|
41
|
+
scope = Marshal.restore(@redis.get("query-#{scope_key}"))
|
42
|
+
|
43
|
+
if in_scope?(scope, object)
|
44
|
+
ident = "query-keys-#{scope_key}"
|
45
|
+
elements = @redis.smembers(ident)
|
46
|
+
@redis.del(ident)
|
47
|
+
elements
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
keys.flatten.compact
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/taggable_cache/store.rb
CHANGED
@@ -1,85 +1,2 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
class TaggableCache::Store
|
5
|
-
def initialize
|
6
|
-
@redis = Redis.new :host => ENV['REDIS_HOST'] || '127.0.0.1',
|
7
|
-
:port => ENV['REDIS_PORT'] ? ENV['REDIS_PORT'].to_i : 6379
|
8
|
-
end
|
9
|
-
|
10
|
-
def id_for(obj)
|
11
|
-
if obj.is_a? Class
|
12
|
-
obj.to_s.downcase
|
13
|
-
elsif obj.is_a? ActiveRecord::Base
|
14
|
-
if obj.persisted?
|
15
|
-
"#{obj.class.to_s.downcase}-#{obj.id}"
|
16
|
-
else
|
17
|
-
id_for(obj.class)
|
18
|
-
end
|
19
|
-
elsif obj.is_a? Arel::SelectManager
|
20
|
-
"query-keys-#{Digest::MD5.hexdigest(obj.to_sql)}"
|
21
|
-
elsif obj.is_a? ActiveRecord::Relation
|
22
|
-
id_for(obj.arel)
|
23
|
-
else
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def add(tag, *members)
|
29
|
-
members.each do |element|
|
30
|
-
add_scope(tag, element) if is_scope? element
|
31
|
-
ident = id_for(element)
|
32
|
-
@redis.sadd ident, tag unless ident.nil?
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def get(*members)
|
37
|
-
members.map do |tag|
|
38
|
-
ident = id_for(tag)
|
39
|
-
elements = @redis.smembers(ident)
|
40
|
-
@redis.del(ident)
|
41
|
-
elements
|
42
|
-
end.flatten.compact
|
43
|
-
end
|
44
|
-
|
45
|
-
def is_scope?(scope)
|
46
|
-
(scope.is_a? ActiveRecord::Relation) || (scope.is_a? Arel::SelectManager)
|
47
|
-
end
|
48
|
-
|
49
|
-
def add_scope(tag, scope)
|
50
|
-
scope = scope.arel if scope.is_a? ActiveRecord::Relation
|
51
|
-
table_name = scope.froms.first.name
|
52
|
-
query_fingerprint = Digest::MD5.hexdigest(scope.to_sql)
|
53
|
-
|
54
|
-
@redis.sadd "#{table_name}-scopes", "#{query_fingerprint}"
|
55
|
-
@redis.set "query-#{query_fingerprint}", Marshal.dump(scope)
|
56
|
-
end
|
57
|
-
|
58
|
-
def in_scope(scope, object)
|
59
|
-
return false unless object.persisted?
|
60
|
-
|
61
|
-
query = scope.where(scope.froms.first[:id].eq(object.id)).to_sql
|
62
|
-
|
63
|
-
object.class.connection.select_all(query).length > 0
|
64
|
-
end
|
65
|
-
|
66
|
-
def get_scope(*members)
|
67
|
-
keys = members.delete_if{|a| not a.is_a? ActiveRecord::Base }.map do |object|
|
68
|
-
|
69
|
-
table_redis_key = "#{object.class.table_name}-scopes"
|
70
|
-
|
71
|
-
@redis.smembers(table_redis_key).map do |scope_key|
|
72
|
-
scope = Marshal.restore(@redis.get("query-#{scope_key}"))
|
73
|
-
|
74
|
-
if in_scope(scope, object)
|
75
|
-
ident = "query-keys-#{scope_key}"
|
76
|
-
elements = @redis.smembers(ident)
|
77
|
-
@redis.del(ident)
|
78
|
-
elements
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
keys.flatten.compact
|
84
|
-
end
|
85
|
-
end
|
1
|
+
require 'taggable_cache/store/base'
|
2
|
+
require 'taggable_cache/store/redis'
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
2
|
+
|
3
|
+
describe TaggableCache::Store do
|
4
|
+
it "should expire all present cache entries with depends_on" do
|
5
|
+
Rails.cache.write 'expireme', 'value', :depends_on => Page
|
6
|
+
Rails.cache.read('expireme').should == 'value'
|
7
|
+
|
8
|
+
Rails.cache.expire_all
|
9
|
+
|
10
|
+
Rails.cache.read('expireme').should be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should not expire cache entries without depends_on" do
|
14
|
+
Rails.cache.write 'expireme', 'value2', :depends_on => Page
|
15
|
+
Rails.cache.read('expireme').should == 'value2'
|
16
|
+
|
17
|
+
Rails.cache.expire_all
|
18
|
+
|
19
|
+
Rails.cache.read('expireme').should be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should expire cache entries, elements for which were already deleted" do
|
23
|
+
page = Page.new
|
24
|
+
page.save!
|
25
|
+
|
26
|
+
#creating second one
|
27
|
+
Page.new.save!
|
28
|
+
|
29
|
+
Rails.cache.write("new_page_contents", 'lorem ipsum di amet', :depends_on => page)
|
30
|
+
|
31
|
+
page.delete # delete does not call any callbacks
|
32
|
+
|
33
|
+
Rails.cache.read('new_page_contents').should == 'lorem ipsum di amet'
|
34
|
+
|
35
|
+
Rails.cache.expire_all
|
36
|
+
|
37
|
+
Rails.cache.read('new_page_contents').should be_nil
|
38
|
+
end
|
39
|
+
end
|
@@ -9,7 +9,7 @@ describe TaggableCache::Store do
|
|
9
9
|
it "should fall back to defaults if no settings given" do
|
10
10
|
Redis.should_receive(:new).with(:host => '127.0.0.1', :port => 6379)
|
11
11
|
|
12
|
-
TaggableCache::Store.new
|
12
|
+
TaggableCache::Store::Redis.new
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should use ENV settings" do
|
@@ -18,6 +18,6 @@ describe TaggableCache::Store do
|
|
18
18
|
|
19
19
|
Redis.should_receive(:new).with(:host => 'hostname.lvh.me', :port => 1234)
|
20
20
|
|
21
|
-
TaggableCache::Store.new
|
21
|
+
TaggableCache::Store::Redis.new
|
22
22
|
end
|
23
23
|
end
|
@@ -4,13 +4,13 @@ describe TaggableCache::Store do
|
|
4
4
|
describe "connection to redis" do
|
5
5
|
it "should use default settings" do
|
6
6
|
Redis.should_receive(:new)
|
7
|
-
TaggableCache::Store.new
|
7
|
+
TaggableCache::Store::Redis.new
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
describe "adding tags" do
|
12
12
|
before :all do
|
13
|
-
@object = TaggableCache::Store.new
|
13
|
+
@object = TaggableCache::Store::Redis.new
|
14
14
|
@redis = Redis.new
|
15
15
|
@redis.flushall
|
16
16
|
end
|
@@ -39,6 +39,19 @@ describe TaggableCache::Store do
|
|
39
39
|
|
40
40
|
@object.id_for(Page.order(:id)).should_not == @object.id_for(Page.order(:name).arel)
|
41
41
|
end
|
42
|
+
|
43
|
+
it "should try to parse well-formatted hash to AR object key" do
|
44
|
+
key = @object.id_for(page = Page.create)
|
45
|
+
key.should == @object.id_for({:cls => :page, :id => page.id})
|
46
|
+
key.should == @object.id_for({:cls => Page, :id => page.id})
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should ignore bad-formatted hashes" do
|
50
|
+
@object.id_for({:cls => :page}).should be_nil
|
51
|
+
@object.id_for({:cls => Page}).should be_nil
|
52
|
+
@object.id_for({:id => 543}).should be_nil
|
53
|
+
@object.id_for({:sdfasdf => 345}).should be_nil
|
54
|
+
end
|
42
55
|
end
|
43
56
|
|
44
57
|
describe "is_scope?" do
|
@@ -74,17 +87,17 @@ describe TaggableCache::Store do
|
|
74
87
|
@redis.smembers("query-keys-#{key}").should == ['tag_scoped']
|
75
88
|
end
|
76
89
|
|
77
|
-
it "should process 'in_scope' right way" do
|
90
|
+
it "should process 'in_scope?' right way" do
|
78
91
|
bob = Page.create(:name => 'bob')
|
79
92
|
jack = Page.create(:name => 'jack')
|
80
93
|
|
81
|
-
@object.in_scope(Page.where(:name => 'bob'), bob).should be_true
|
82
|
-
@object.in_scope(Page.where(:name => 'bob'), jack).should be_false
|
94
|
+
@object.in_scope?(Page.where(:name => 'bob'), bob).should be_true
|
95
|
+
@object.in_scope?(Page.where(:name => 'bob'), jack).should be_false
|
83
96
|
|
84
|
-
@object.in_scope(Page.order(:id), Page.create).should be_true
|
97
|
+
@object.in_scope?(Page.order(:id), Page.create).should be_true
|
85
98
|
|
86
99
|
#unsaved obj(without id)
|
87
|
-
@object.in_scope(Page.order(:id), Page.new).should be_false
|
100
|
+
@object.in_scope?(Page.order(:id), Page.new).should be_false
|
88
101
|
end
|
89
102
|
|
90
103
|
describe "get_scope" do
|
data/taggable-cache.gemspec
CHANGED
@@ -9,8 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.version = TaggableCache::VERSION
|
10
10
|
|
11
11
|
s.authors = ["Alex Rozumey"]
|
12
|
-
s.
|
13
|
-
s.description = "This gem simplifies cache expiration in rails"
|
12
|
+
s.description = "It makes cache expiration in rails much simpler"
|
14
13
|
s.email = "brain-geek@yandex.ua"
|
15
14
|
|
16
15
|
s.extra_rdoc_files = [
|
@@ -26,7 +25,7 @@ Gem::Specification.new do |s|
|
|
26
25
|
s.homepage = "http://github.com/brain-geek/taggable-cache"
|
27
26
|
s.licenses = ["MIT"]
|
28
27
|
s.rubygems_version = "1.8.15"
|
29
|
-
s.summary = "This gem simplifies cache expiration in rails by
|
28
|
+
s.summary = "This gem simplifies cache expiration in rails by expanding rails cache methods."
|
30
29
|
|
31
30
|
#s.add_dependency(%q<rails>, [">= 3.1.0"])
|
32
31
|
s.add_dependency(%q<railties>, [">= 3.1.0"])
|
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.4.
|
4
|
+
version: 0.4.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: railties
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: 3.1.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.1.0
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: actionpack
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: 3.1.0
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 3.1.0
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: activerecord
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: 3.1.0
|
44
54
|
type: :runtime
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.1.0
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: redis
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ! '>='
|
@@ -54,8 +69,13 @@ dependencies:
|
|
54
69
|
version: 2.2.0
|
55
70
|
type: :runtime
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
58
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.2.0
|
78
|
+
description: It makes cache expiration in rails much simpler
|
59
79
|
email: brain-geek@yandex.ua
|
60
80
|
executables: []
|
61
81
|
extensions: []
|
@@ -64,6 +84,7 @@ extra_rdoc_files:
|
|
64
84
|
- README.rdoc
|
65
85
|
files:
|
66
86
|
- .gitignore
|
87
|
+
- .rvmrc
|
67
88
|
- .travis.yml
|
68
89
|
- CHANGELOG.md
|
69
90
|
- Gemfile
|
@@ -74,9 +95,13 @@ files:
|
|
74
95
|
- gemfiles/Gemfile-rails.3.2.x
|
75
96
|
- gemfiles/Gemfile.shared
|
76
97
|
- lib/taggable_cache.rb
|
77
|
-
- lib/taggable_cache/extensions.rb
|
98
|
+
- lib/taggable_cache/extensions/action_controller.rb
|
99
|
+
- lib/taggable_cache/extensions/active_record.rb
|
100
|
+
- lib/taggable_cache/extensions/cache_store.rb
|
78
101
|
- lib/taggable_cache/railtie.rb
|
79
102
|
- lib/taggable_cache/store.rb
|
103
|
+
- lib/taggable_cache/store/base.rb
|
104
|
+
- lib/taggable_cache/store/redis.rb
|
80
105
|
- lib/taggable_cache/version.rb
|
81
106
|
- spec/integration/rails_cache_spec.rb
|
82
107
|
- spec/internal/app/controller/action_caching_controller.rb
|
@@ -89,6 +114,7 @@ files:
|
|
89
114
|
- spec/requests/action_caching_controller_spec.rb
|
90
115
|
- spec/requests/fragment_caching_controller_spec.rb
|
91
116
|
- spec/spec_helper.rb
|
117
|
+
- spec/taggable-cache/expire_all_spec.rb
|
92
118
|
- spec/taggable-cache/settings_spec.rb
|
93
119
|
- spec/taggable-cache/store_spec.rb
|
94
120
|
- taggable-cache.gemspec
|
@@ -107,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
133
|
version: '0'
|
108
134
|
segments:
|
109
135
|
- 0
|
110
|
-
hash:
|
136
|
+
hash: -997136803
|
111
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
138
|
none: false
|
113
139
|
requirements:
|
@@ -116,12 +142,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
142
|
version: '0'
|
117
143
|
segments:
|
118
144
|
- 0
|
119
|
-
hash:
|
145
|
+
hash: -997136803
|
120
146
|
requirements: []
|
121
147
|
rubyforge_project:
|
122
|
-
rubygems_version: 1.8.
|
148
|
+
rubygems_version: 1.8.24
|
123
149
|
signing_key:
|
124
150
|
specification_version: 3
|
125
|
-
summary: This gem simplifies cache expiration in rails by
|
126
|
-
to rails cache.
|
151
|
+
summary: This gem simplifies cache expiration in rails by expanding rails cache methods.
|
127
152
|
test_files: []
|
@@ -1,92 +0,0 @@
|
|
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
|
-
def write_with_taggable(name, value, options = nil)
|
11
|
-
if !options.nil? && options.has_key?(:depends_on)
|
12
|
-
add_tags(name, *options[:depends_on])
|
13
|
-
end
|
14
|
-
|
15
|
-
write_without_taggable(name, value, options)
|
16
|
-
end
|
17
|
-
|
18
|
-
alias_method_chain :write, :taggable
|
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
|