simple_cacheable 1.3.2 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b46d1110354d90d106fe5abdfed1eaa6801dd7e4
4
+ data.tar.gz: 763dac9a0c34135095974d09bb2575fbc5106ed2
5
+ SHA512:
6
+ metadata.gz: f0fd40d41856c6efb7ecdfa1d8263ab2178b98c4cc8656d5bde2f3e67d71029c8cdebacf72a9d127abd775867d1d452fe86e8b122ec8f8adb315b9fab444999b
7
+ data.tar.gz: 322aad0ed21db8769cc06557df6461f8e8a29ddad18597922a4410480dc71a3d639217ea07a88b3c861db899802b4cf05c615242dc5069a9aab55325bfb0983a
data/.gitignore CHANGED
@@ -1,5 +1,4 @@
1
1
  *.gem
2
2
  .bundle
3
- Gemfile.lock
4
3
  pkg/
5
4
  bin/
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ cacheable
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0
data/ChangeLog ADDED
@@ -0,0 +1,7 @@
1
+ 1.3.3
2
+ * File Reorganization
3
+ * Rails 4 Compatibility
4
+ * Class Method Caching can accept arguments
5
+ * Class Method Caching
6
+ * has_one through association caching
7
+ * has_and_belongs_to_many association caching
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source "http://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  platforms :ruby do
7
- gem "sqlite3-ruby"
7
+ gem "sqlite3"
8
8
  gem "memcached"
9
9
  end
10
10
 
@@ -12,6 +12,4 @@ platforms :jruby do
12
12
  gem "activerecord-jdbc-adapter"
13
13
  gem "activerecord-jdbcsqlite3-adapter"
14
14
  gem "jruby-memcached"
15
- end
16
-
17
- gem "debugger"
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,115 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ simple_cacheable (1.3.2)
5
+ rails (>= 3.0.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ actionmailer (4.0.0)
11
+ actionpack (= 4.0.0)
12
+ mail (~> 2.5.3)
13
+ actionpack (4.0.0)
14
+ activesupport (= 4.0.0)
15
+ builder (~> 3.1.0)
16
+ erubis (~> 2.7.0)
17
+ rack (~> 1.5.2)
18
+ rack-test (~> 0.6.2)
19
+ activemodel (4.0.0)
20
+ activesupport (= 4.0.0)
21
+ builder (~> 3.1.0)
22
+ activerecord (4.0.0)
23
+ activemodel (= 4.0.0)
24
+ activerecord-deprecated_finders (~> 1.0.2)
25
+ activesupport (= 4.0.0)
26
+ arel (~> 4.0.0)
27
+ activerecord-deprecated_finders (1.0.3)
28
+ activerecord-jdbc-adapter (1.2.2.1)
29
+ activerecord-jdbcsqlite3-adapter (1.2.2.1)
30
+ activerecord-jdbc-adapter (~> 1.2.2.1)
31
+ jdbc-sqlite3 (~> 3.7.2)
32
+ activesupport (4.0.0)
33
+ i18n (~> 0.6, >= 0.6.4)
34
+ minitest (~> 4.2)
35
+ multi_json (~> 1.3)
36
+ thread_safe (~> 0.1)
37
+ tzinfo (~> 0.3.37)
38
+ arel (4.0.0)
39
+ atomic (1.1.10)
40
+ atomic (1.1.10-java)
41
+ builder (3.1.4)
42
+ diff-lcs (1.1.3)
43
+ erubis (2.7.0)
44
+ hike (1.2.3)
45
+ i18n (0.6.4)
46
+ jdbc-sqlite3 (3.7.2)
47
+ jruby-memcached (0.5.1)
48
+ mail (2.5.4)
49
+ mime-types (~> 1.16)
50
+ treetop (~> 1.4.8)
51
+ memcached (1.4.6)
52
+ metaclass (0.0.1)
53
+ mime-types (1.23)
54
+ minitest (4.7.5)
55
+ mocha (0.10.5)
56
+ metaclass (~> 0.0.1)
57
+ multi_json (1.7.7)
58
+ polyglot (0.3.3)
59
+ rack (1.5.2)
60
+ rack-test (0.6.2)
61
+ rack (>= 1.0)
62
+ rails (4.0.0)
63
+ actionmailer (= 4.0.0)
64
+ actionpack (= 4.0.0)
65
+ activerecord (= 4.0.0)
66
+ activesupport (= 4.0.0)
67
+ bundler (>= 1.3.0, < 2.0)
68
+ railties (= 4.0.0)
69
+ sprockets-rails (~> 2.0.0)
70
+ railties (4.0.0)
71
+ actionpack (= 4.0.0)
72
+ activesupport (= 4.0.0)
73
+ rake (>= 0.8.7)
74
+ thor (>= 0.18.1, < 2.0)
75
+ rake (10.1.0)
76
+ rspec (2.8.0)
77
+ rspec-core (~> 2.8.0)
78
+ rspec-expectations (~> 2.8.0)
79
+ rspec-mocks (~> 2.8.0)
80
+ rspec-core (2.8.0)
81
+ rspec-expectations (2.8.0)
82
+ diff-lcs (~> 1.1.2)
83
+ rspec-mocks (2.8.0)
84
+ sprockets (2.10.0)
85
+ hike (~> 1.2)
86
+ multi_json (~> 1.0)
87
+ rack (~> 1.0)
88
+ tilt (~> 1.1, != 1.3.0)
89
+ sprockets-rails (2.0.0)
90
+ actionpack (>= 3.0)
91
+ activesupport (>= 3.0)
92
+ sprockets (~> 2.8)
93
+ sqlite3 (1.3.7)
94
+ thor (0.18.1)
95
+ thread_safe (0.1.0)
96
+ atomic
97
+ tilt (1.4.1)
98
+ treetop (1.4.14)
99
+ polyglot
100
+ polyglot (>= 0.3.1)
101
+ tzinfo (0.3.37)
102
+
103
+ PLATFORMS
104
+ java
105
+ ruby
106
+
107
+ DEPENDENCIES
108
+ activerecord-jdbc-adapter
109
+ activerecord-jdbcsqlite3-adapter
110
+ jruby-memcached
111
+ memcached
112
+ mocha
113
+ rspec
114
+ simple_cacheable!
115
+ sqlite3
data/README.md CHANGED
@@ -76,7 +76,7 @@ Gotchas
76
76
 
77
77
  Caching, and caching invalidation specifically, can be hard and confusing. Simple Cacheable methods should
78
78
  expire correctly in most cases. Be careful using `with_method` and `with_class_method`, they should
79
- specifically not be used to return collections. This is demonstrated well Tobias Lutke's presentation: [Rockstar Memcaching][2].
79
+ specifically not be used to return collections. This is demonstrated well in Tobias Lutke's presentation: [Rockstar Memcaching][2].
80
80
 
81
81
  Copyright © 2011 Richard Huang (flyerhzm@gmail.com), released under the MIT license
82
82
 
@@ -0,0 +1,15 @@
1
+ require "cacheable/types/key_cache"
2
+ require "cacheable/types/attribute_cache"
3
+ require "cacheable/types/method_cache"
4
+ require "cacheable/types/class_method_cache"
5
+ require "cacheable/types/association_cache"
6
+
7
+ module Cacheable
8
+ module Caches
9
+ include Cacheable::KeyCache
10
+ include Cacheable::AttributeCache
11
+ include Cacheable::MethodCache
12
+ include Cacheable::ClassMethodCache
13
+ include Cacheable::AssocationCache
14
+ end
15
+ end
@@ -0,0 +1,53 @@
1
+ module Cacheable
2
+ module Expiry
3
+ def expire_model_cache
4
+ expire_key_cache if self.class.cached_key
5
+ expire_attribute_cache if self.class.cached_indices.present?
6
+ expire_all_attribute_cache if self.class.cached_indices.present?
7
+ expire_method_cache if self.class.cached_methods.present?
8
+ expire_class_method_cache if self.class.cached_class_methods.present?
9
+
10
+ if self.class.cached_associations.present?
11
+ self.class.cached_associations.each do |assoc|
12
+ expire_association_cache(assoc)
13
+ end
14
+ end
15
+ end
16
+
17
+ def expire_key_cache
18
+ Rails.cache.delete model_cache_key
19
+ end
20
+
21
+ def expire_attribute_cache
22
+ self.class.cached_indices.each do |attribute, values|
23
+ value = self.send(attribute)
24
+ Rails.cache.delete self.class.attribute_cache_key(attribute, value)
25
+ end
26
+ end
27
+
28
+ def expire_all_attribute_cache
29
+ self.class.cached_indices.each do |attribute, values|
30
+ value = self.send(attribute)
31
+ Rails.cache.delete self.class.all_attribute_cache_key(attribute, value)
32
+ end
33
+ end
34
+
35
+ def expire_method_cache
36
+ self.class.cached_methods.each do |meth|
37
+ Rails.cache.delete method_cache_key(meth)
38
+ end
39
+ end
40
+
41
+ def expire_class_method_cache
42
+ self.class.cached_class_methods.each do |meth, args|
43
+ args.each do |arg|
44
+ Rails.cache.delete self.class.class_method_cache_key(meth, arg)
45
+ end
46
+ end
47
+ end
48
+
49
+ def expire_association_cache(name)
50
+ Rails.cache.delete have_association_cache_key(name)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,54 @@
1
+ module Cacheable
2
+ module Keys
3
+
4
+ def self.included(base)
5
+ base.extend(Cacheable::Keys::ClassKeys)
6
+ base.send :include, Cacheable::Keys::InstanceKeys
7
+ end
8
+
9
+ module ClassKeys
10
+
11
+ def attribute_cache_key(attribute, value)
12
+ "#{name.tableize}/attribute/#{attribute}/#{URI.escape(value.to_s)}"
13
+ end
14
+
15
+ def all_attribute_cache_key(attribute, value)
16
+ "#{name.tableize}/attribute/#{attribute}/all/#{URI.escape(value.to_s)}"
17
+ end
18
+
19
+ def class_method_cache_key(meth, *args)
20
+ key = "#{name.tableize}/class_method/#{meth}"
21
+ args.flatten!
22
+ key += "/#{args.join('+')}" if args.any?
23
+ return key
24
+ end
25
+
26
+ end
27
+
28
+ module InstanceKeys
29
+
30
+ def model_cache_key
31
+ "#{self.class.name.tableize}/#{self.id.to_i}"
32
+ end
33
+
34
+ def method_cache_key(meth)
35
+ "#{model_cache_key}/method/#{meth}"
36
+ end
37
+
38
+ def belong_association_cache_key(name, polymorphic=nil)
39
+ name = name.to_s if name.is_a?(Symbol)
40
+ if polymorphic
41
+ "#{self.send("#{name}_type").tableize}/#{self.send("#{name}_id")}"
42
+ else
43
+ "#{name.tableize}/#{self.send(name + "_id")}"
44
+ end
45
+ end
46
+
47
+ def have_association_cache_key(name)
48
+ "#{model_cache_key}/association/#{name}"
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,92 @@
1
+ module Cacheable
2
+ module AssocationCache
3
+
4
+ def with_association(*association_names)
5
+ self.cached_associations = association_names
6
+
7
+ association_names.each do |association_name|
8
+ association = reflect_on_association(association_name)
9
+
10
+ if :belongs_to == association.macro
11
+ polymorphic = association.options[:polymorphic]
12
+ polymorphic ||= false
13
+
14
+ define_method("cached_#{association_name}") do
15
+ Rails.cache.fetch belong_association_cache_key(association_name, polymorphic) do
16
+ send(association_name)
17
+ end
18
+ end
19
+ else
20
+ if through_reflection_name = association.options[:through]
21
+ through_association = self.reflect_on_association(through_reflection_name)
22
+
23
+ # FIXME it should be the only reflection but I'm not 100% positive
24
+ reverse_through_association = through_association.klass.reflect_on_all_associations(:belongs_to).first
25
+
26
+ # In a through association it doesn't have to be a belongs_to
27
+ reverse_association = association.klass.reflect_on_all_associations(:belongs_to).find { |reverse_association|
28
+ reverse_association.options[:polymorphic] ? reverse_association.name == association.source_reflection.options[:as] : reverse_association.klass == self
29
+ }
30
+ if reverse_association
31
+ association.klass.class_eval do
32
+ after_commit "expire_#{association_name}_cache".to_sym
33
+
34
+ define_method("expire_#{association_name}_cache") do
35
+ if respond_to? "expire_#{reverse_association.name}_cache".to_sym
36
+ # cached_viewable.expire_association_cache
37
+ send("cached_#{reverse_association.name}").expire_association_cache(association_name)
38
+ else
39
+ send(reverse_association.name).send(reverse_through_association.name).expire_association_cache(association_name)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ elsif :has_and_belongs_to_many == association.macro
45
+ # No such thing as a polymorphic has_and_belongs_to_many
46
+ reverse_association = association.klass.reflect_on_all_associations(:has_and_belongs_to_many).find { |reverse_association|
47
+ reverse_association.klass == self
48
+ }
49
+
50
+ association.klass.class_eval do
51
+ after_commit "expire_#{association_name}_cache".to_sym
52
+
53
+ define_method "expire_#{association_name}_cache" do
54
+ if respond_to? "cached_#{reverse_association.name}".to_sym
55
+ # cached_viewable.expire_association_cache
56
+ send("cached_#{reverse_association.name}").expire_association_cache(association_name)
57
+ else
58
+ send("#{reverse_association.name}").each do |assoc|
59
+ assoc.expire_association_cache(association_name)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ else
65
+ reverse_association = association.klass.reflect_on_all_associations(:belongs_to).find { |reverse_association|
66
+ reverse_association.options[:polymorphic] ? reverse_association.name == association.options[:as] : reverse_association.klass == self
67
+ }
68
+
69
+ association.klass.class_eval do
70
+ after_commit "expire_#{association_name}_cache".to_sym
71
+
72
+ define_method "expire_#{association_name}_cache" do
73
+ if respond_to? "cached_#{reverse_association.name}".to_sym
74
+ send("cached_#{reverse_association.name}").expire_association_cache(association_name)
75
+ else
76
+ send("#{reverse_association.name}").expire_association_cache(association_name)
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ define_method("cached_#{association_name}") do
83
+ Rails.cache.fetch have_association_cache_key(association_name) do
84
+ send(association_name).respond_to?(:to_a) ? send(association_name).to_a : send(association_name)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,30 @@
1
+ module Cacheable
2
+ module AttributeCache
3
+ def with_attribute(*attributes)
4
+ self.cached_indices = attributes.inject({}) { |indices, attribute| indices[attribute] = {} }
5
+
6
+ class_eval do
7
+ after_commit :expire_attribute_cache, :on => :update
8
+ after_commit :expire_all_attribute_cache, :on => :update
9
+ end
10
+
11
+ attributes.each do |attribute|
12
+ define_singleton_method("find_cached_by_#{attribute}") do |value|
13
+ self.cached_indices["#{attribute}"] ||= []
14
+ self.cached_indices["#{attribute}"] << value
15
+ Rails.cache.fetch attribute_cache_key("#{attribute}", value) do
16
+ self.send("find_by_#{attribute}", value)
17
+ end
18
+ end
19
+
20
+ define_singleton_method("find_cached_all_by_#{attribute}") do |value|
21
+ self.cached_indices["#{attribute}"] ||= []
22
+ self.cached_indices["#{attribute}"] << value
23
+ Rails.cache.fetch all_attribute_cache_key("#{attribute}", value) do
24
+ self.send("find_all_by_#{attribute}", value)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ module Cacheable
2
+ module ClassMethodCache
3
+ # Cached class method
4
+ # Should expire on any instance save
5
+ def with_class_method(*methods)
6
+ self.cached_class_methods = methods.inject({}) { |indices, meth| indices[meth] = {} }
7
+
8
+ class_eval do
9
+ after_commit :expire_class_method_cache, on: :update
10
+ end
11
+
12
+ methods.each do |meth|
13
+ define_singleton_method("cached_#{meth}") do |*args|
14
+ self.cached_class_methods["#{meth}"] ||= []
15
+ self.cached_class_methods["#{meth}"] << args
16
+ Rails.cache.fetch class_method_cache_key(meth, args) do
17
+ self.method(meth).arity == 0 ? send(meth) : send(meth, *args)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module Cacheable
2
+ module KeyCache
3
+ def with_key
4
+ self.cached_key = true
5
+
6
+ class_eval do
7
+ after_commit :expire_key_cache, on: :update
8
+ end
9
+
10
+ define_singleton_method("find_cached") do |id|
11
+ Rails.cache.fetch "#{name.tableize}/" + id.to_i.to_s do
12
+ self.find(id)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module Cacheable
2
+ module MethodCache
3
+ def with_method(*methods)
4
+ self.cached_methods = methods
5
+
6
+ class_eval do
7
+ after_commit :expire_method_cache, :on => :update
8
+ end
9
+
10
+ methods.each do |meth|
11
+ define_method("cached_#{meth}") do
12
+ Rails.cache.fetch method_cache_key(meth) do
13
+ send(meth)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module Cacheable
2
- VERSION = "1.3.2"
2
+ VERSION = "1.3.3"
3
3
  end