generation_cacheable 1.0.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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/ChangeLog +2 -0
  7. data/Gemfile +16 -0
  8. data/README.md +33 -0
  9. data/Rakefile +8 -0
  10. data/generation_cacheable.gemspec +23 -0
  11. data/lib/gen_cache.rb +32 -0
  12. data/lib/gen_cache/cache_io/fetching.rb +78 -0
  13. data/lib/gen_cache/cache_io/formatting.rb +75 -0
  14. data/lib/gen_cache/cache_io/parsing.rb +66 -0
  15. data/lib/gen_cache/cache_types/association_cache.rb +50 -0
  16. data/lib/gen_cache/cache_types/attribute_cache.rb +30 -0
  17. data/lib/gen_cache/cache_types/class_method_cache.rb +23 -0
  18. data/lib/gen_cache/cache_types/key_cache.rb +14 -0
  19. data/lib/gen_cache/cache_types/method_cache.rb +28 -0
  20. data/lib/gen_cache/caches.rb +15 -0
  21. data/lib/gen_cache/expiry.rb +37 -0
  22. data/lib/gen_cache/keys.rb +70 -0
  23. data/lib/gen_cache/version.rb +3 -0
  24. data/spec/gen_cache/cache_io/fetching_spec.rb +41 -0
  25. data/spec/gen_cache/cache_io/formatting_spec.rb +59 -0
  26. data/spec/gen_cache/cache_io/parsing_spec.rb +47 -0
  27. data/spec/gen_cache/cache_types/association_cache_spec.rb +313 -0
  28. data/spec/gen_cache/cache_types/attribute_cache_spec.rb +98 -0
  29. data/spec/gen_cache/cache_types/class_method_cache_spec.rb +72 -0
  30. data/spec/gen_cache/cache_types/key_cache_spec.rb +34 -0
  31. data/spec/gen_cache/cache_types/method_cache_spec.rb +108 -0
  32. data/spec/gen_cache/expiry_spec.rb +182 -0
  33. data/spec/gen_cache/keys_spec.rb +66 -0
  34. data/spec/gen_cache_spec.rb +76 -0
  35. data/spec/models/account.rb +7 -0
  36. data/spec/models/comment.rb +9 -0
  37. data/spec/models/descendant.rb +20 -0
  38. data/spec/models/group.rb +6 -0
  39. data/spec/models/image.rb +11 -0
  40. data/spec/models/location.rb +3 -0
  41. data/spec/models/post.rb +31 -0
  42. data/spec/models/tag.rb +6 -0
  43. data/spec/models/user.rb +54 -0
  44. data/spec/spec_helper.rb +96 -0
  45. metadata +149 -0
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ describe GenCache do
4
+ let(:cache) { Rails.cache }
5
+ let(:user) { User.create(:login => 'flyerhzm') }
6
+ let(:descendant) { Descendant.create(:login => "scotterc")}
7
+
8
+ before :all do
9
+ @post1 = user.posts.create(:title => 'post1')
10
+ @post2 = user.posts.create(:title => 'post2')
11
+ @post3 = descendant.posts.create(:title => 'post3')
12
+ end
13
+
14
+ before :each do
15
+ cache.clear
16
+ user.reload
17
+ end
18
+
19
+ context "with_attribute" do
20
+ it "should not cache User.find_by_login" do
21
+ key = GenCache.attribute_key(User, :login, "flyerhzm")
22
+ Rails.cache.read(key[:key]).should be_nil
23
+ end
24
+
25
+ it "should cache by User.find_by_login" do
26
+ User.find_cached_by_login("flyerhzm").should == user
27
+ key = GenCache.attribute_key(User, :login, 'flyerhzm')
28
+ Rails.cache.read(key[:key]).should == {:class => user.class, 'attributes' => user.attributes}
29
+ end
30
+
31
+ it "should get cached by User.find_by_login multiple times" do
32
+ User.find_cached_by_login("flyerhzm")
33
+ User.find_cached_by_login("flyerhzm").should == user
34
+ end
35
+
36
+ it "should escape whitespace" do
37
+ new_user = User.create(:login => "user space")
38
+ User.find_cached_by_login("user space").should == new_user
39
+ end
40
+
41
+ it "should handle fixed numbers" do
42
+ Post.find_cached_by_user_id(user.id).should == @post1
43
+ key = GenCache.attribute_key(Post, :user_id, user.id)
44
+ Rails.cache.read(key[:key]).should == {:class => @post1.class, 'attributes' => @post1.attributes}
45
+ end
46
+
47
+ context "find_all" do
48
+ it "should not cache Post.find_all_by_user_id" do
49
+ key = GenCache.attribute_key(Post, :user_id, user.id, all: true)
50
+ Rails.cache.read(key[:key]).should be_nil
51
+ end
52
+
53
+ it "should cache by Post.find_cached_all_by_user_id" do
54
+ Post.find_cached_all_by_user_id(user.id).should == [@post1, @post2]
55
+ key = GenCache.attribute_key(Post, :user_id, user.id, all: true)
56
+ Rails.cache.read(key[:key]).should == [{:class => Post, 'attributes' => @post1.attributes},
57
+ {:class => Post, 'attributes' => @post2.attributes}]
58
+ end
59
+
60
+ it "should get cached by Post.find_cached_all_by_user_id multiple times" do
61
+ Post.find_cached_all_by_user_id(user.id)
62
+ Post.find_cached_all_by_user_id(user.id).should == [@post1, @post2]
63
+ end
64
+
65
+ end
66
+ end
67
+
68
+ context "descendant" do
69
+ it "should not cache Descendant.find_by_login" do
70
+ key = GenCache.attribute_key(Descendant, :login, "scotterc")
71
+ Rails.cache.read(key[:key]).should be_nil
72
+ end
73
+
74
+ it "should cache by Descendant.find_by_login" do
75
+ Descendant.find_cached_by_login("scotterc").should == descendant
76
+ key = GenCache.attribute_key(Descendant, :login, "scotterc")
77
+ Rails.cache.read(key[:key]).should == {:class => Descendant, 'attributes' => descendant.attributes}
78
+ end
79
+
80
+ it "should get cached by Descendant.find_by_login multiple times" do
81
+ Descendant.find_cached_by_login("scotterc")
82
+ Descendant.find_cached_by_login("scotterc").should == descendant
83
+ end
84
+
85
+ it "should escape whitespace" do
86
+ new_descendant = Descendant.create(:login => "descendant space")
87
+ Descendant.find_cached_by_login("descendant space").should == new_descendant
88
+ end
89
+
90
+ it "maintains cached methods" do
91
+ key = GenCache.method_key(descendant, :name)
92
+ Rails.cache.read(key[:key]).should be_nil
93
+ descendant.cached_name.should == descendant.name
94
+ Rails.cache.read(key[:key]).should == descendant.name
95
+ end
96
+ end
97
+
98
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe GenCache do
4
+ let(:cache) { Rails.cache }
5
+ let(:user) { User.create(:login => 'flyerhzm', :email => 'flyerhzm@mail.com') }
6
+
7
+ before :all do
8
+ @post1 = user.posts.create(:title => 'post1')
9
+ @post2 = user.posts.create(:title => 'post2')
10
+ end
11
+
12
+ before :each do
13
+ cache.clear
14
+ user.reload
15
+ end
16
+
17
+ it "should not cache Post.default_post" do
18
+ key = GenCache.class_method_key(Post, :default_post)
19
+ Rails.cache.read(key[:key]).should be_nil
20
+ end
21
+
22
+ it "should cache Post.default_post" do
23
+ key = GenCache.class_method_key(Post, :default_post)
24
+ Post.cached_default_post.should == @post1
25
+ Rails.cache.read(key[:key]).should == {:class => @post1.class, 'attributes' => @post1.attributes}
26
+ end
27
+
28
+ it "should cache Post.default_post multiple times" do
29
+ Post.cached_default_post
30
+ Post.cached_default_post.should == @post1
31
+ end
32
+
33
+ it "should cache Post.retrieve_with_user_id" do
34
+ result = Post.cached_retrieve_with_user_id(1)
35
+ Post.cached_retrieve_with_user_id(1).should == @post1
36
+ key = GenCache.class_method_key(Post, :retrieve_with_user_id)
37
+ Rails.cache.read(key[:key]).should == {:"1" => {:class => @post1.class, 'attributes' => @post1.attributes }}
38
+ end
39
+
40
+ it "should cache Post.retrieve_with_both with multiple arguments" do
41
+ Post.cached_retrieve_with_both(1, 1).should be_true
42
+ key = GenCache.class_method_key(Post, :retrieve_with_both)
43
+ Rails.cache.read(key[:key]).should == { :"1+1" => true }
44
+ end
45
+
46
+ describe "marshalling" do
47
+
48
+ it "should handle methods with a number argument" do
49
+ result = User.cached_user_with_id(1)
50
+ key = GenCache.class_method_key(User, :user_with_id)
51
+ Rails.cache.read(key[:key]).should == {:"1" => {:class => user.class, 'attributes' => user.attributes }}
52
+ end
53
+
54
+ it "should handle methods with a string argument" do
55
+ result = User.cached_user_with_email("flyerhzm@mail.com")
56
+ key = GenCache.class_method_key(User, :user_with_email)
57
+ Rails.cache.read(key[:key]).should == {:"flyerhzm@mail.com" => {:class => user.class, 'attributes' => user.attributes} }
58
+ end
59
+
60
+ it "should handle methods with an array argument" do
61
+ result = User.cached_users_with_ids([ 1 ])
62
+ key = GenCache.class_method_key(User, :users_with_ids)
63
+ Rails.cache.read(key[:key]).should == {:"1" => [{:class => user.class, 'attributes' => user.attributes}]}
64
+ end
65
+
66
+ it "should handle methods with a range argument" do
67
+ result = User.cached_users_with_ids_in( (1...3) )
68
+ key = GenCache.class_method_key(User, "users_with_ids_in")
69
+ Rails.cache.read(key[:key]).should == {:"1...3" => [{:class => user.class, 'attributes' => user.attributes }] }
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe GenCache do
4
+ let(:cache) { Rails.cache }
5
+ let(:user) { User.create(:login => 'flyerhzm') }
6
+
7
+ before :each do
8
+ cache.clear
9
+ user.reload
10
+ end
11
+
12
+ it "should not cache key" do
13
+ cache_key = GenCache.instance_key(User, user.id)
14
+ Rails.cache.read(cache_key[:key]).should be_nil
15
+ end
16
+
17
+ it "should cache by User#id" do
18
+ User.find_cached(user.id).should == user
19
+ cache_key = GenCache.instance_key(User, user.id)
20
+ Rails.cache.read(cache_key[:key]).should == {:class => user.class, 'attributes' => user.attributes}
21
+ end
22
+
23
+ it "should parse formatted cache read successfully" do
24
+ User.find_cached(user.id)
25
+ cache_key = GenCache.instance_key(User, user.id)
26
+ GenCache.fetch(cache_key).should == user
27
+ end
28
+
29
+ it "should get cached by User#id multiple times" do
30
+ User.find_cached(user.id)
31
+ User.find_cached(user.id).should == user
32
+ end
33
+
34
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe GenCache do
4
+ let(:cache) { Rails.cache }
5
+ let(:user) { User.create(:login => 'flyerhzm') }
6
+ let(:descendant) { Descendant.create(:login => "scotterc")}
7
+
8
+ before :all do
9
+ @post1 = user.posts.create(:title => 'post1')
10
+ @post2 = user.posts.create(:title => 'post2')
11
+ @post3 = descendant.posts.create(:title => 'post3')
12
+ end
13
+
14
+ before :each do
15
+ cache.clear
16
+ user.reload
17
+ end
18
+
19
+ it "should not cache User.last_post" do
20
+ key = GenCache.method_key(user, :last_post)
21
+ Rails.cache.read(key[:key]).should be_nil
22
+ end
23
+
24
+ it "should cache User#last_post" do
25
+ user.cached_last_post.should == user.last_post
26
+ coder = GenCache.format_with_key(user.last_post, :object)
27
+ key = GenCache.method_key(user, :last_post)
28
+ Rails.cache.read(key[:key]).should == coder
29
+ end
30
+
31
+ it "should cache User#last_post multiple times" do
32
+ user.cached_last_post
33
+ user.cached_last_post.should == user.last_post
34
+ end
35
+
36
+ context "descendant should inherit methods" do
37
+
38
+ it "should not cache Descendant.last_post" do
39
+ key = GenCache.method_key(user, :last_post)
40
+ Rails.cache.read(key[:key]).should be_nil
41
+ end
42
+
43
+ it "should cache Descendant#last_post" do
44
+ descendant.cached_last_post.should == descendant.last_post
45
+ key = GenCache.method_key(descendant, :last_post)
46
+ coder = GenCache.format_with_key(descendant.last_post, :object)
47
+ Rails.cache.read(key[:key]).should == coder
48
+ end
49
+
50
+ it "should cache Descendant#last_post multiple times" do
51
+ descendant.cached_last_post
52
+ descendant.cached_last_post.should == descendant.last_post
53
+ end
54
+
55
+ context "as well as new methods" do
56
+ it "should not cache Descendant.name" do
57
+ key = GenCache.method_key(descendant, :name)
58
+ Rails.cache.read(key[:key]).should be_nil
59
+ end
60
+
61
+ it "should cache Descendant#name" do
62
+ descendant.cached_name.should == descendant.name
63
+ key = GenCache.method_key(descendant, :name)
64
+ Rails.cache.read(key[:key]).should == descendant.name
65
+ end
66
+
67
+ it "should cache Descendant#name multiple times" do
68
+ descendant.cached_name
69
+ descendant.cached_name.should == descendant.name
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "memoization" do
75
+
76
+ before :each do
77
+ user.instance_variable_set("@cached_last_post", nil)
78
+ user.update_attribute(:login, "pathouse")
79
+ end
80
+
81
+ it "memoizes cache calls" do
82
+ user.instance_variable_get("@cached_last_post").should be_nil
83
+ user.cached_last_post.should == user.last_post
84
+ user.instance_variable_get("@cached_last_post").should == user.last_post
85
+ end
86
+
87
+ it "hits the cache only once" do
88
+ Rails.cache.expects(:read).returns(user.last_post).once
89
+ user.cached_last_post.should == user.last_post
90
+ user.cached_last_post.should == user.last_post
91
+ end
92
+
93
+ describe "bad iv names stripped" do
94
+ it "should deal with queries" do
95
+ user.instance_variable_get("@cached_bad_iv_name_bang").should be_nil
96
+ user.cached_bad_iv_name!.should == 42
97
+ user.instance_variable_get("@cached_bad_iv_name_bang").should == 42
98
+ end
99
+
100
+ it "should deal with bangs" do
101
+ user.instance_variable_get("@cached_bad_iv_name_query").should be_nil
102
+ user.cached_bad_iv_name?.should == 44
103
+ user.instance_variable_get("@cached_bad_iv_name_query").should == 44
104
+ end
105
+ end
106
+ end
107
+
108
+ end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ describe GenCache do
4
+ let(:cache) { Rails.cache }
5
+ let(:user) { User.create(:login => 'flyerhzm') }
6
+ let(:descendant) { Descendant.create(:login => "scotterc")}
7
+
8
+ before :all do
9
+ @post1 = user.posts.create(:title => 'post1')
10
+ user2 = User.create(:login => 'PelegR')
11
+ user2.posts.create(:title => 'post3')
12
+ @post3 = descendant.posts.create(:title => 'post3')
13
+ end
14
+
15
+ before :each do
16
+ cache.clear
17
+ user.reload
18
+ end
19
+
20
+ context "expire_model_cache" do
21
+ it "should delete with_key cache" do
22
+ User.find_cached(user.id)
23
+ key = GenCache.instance_key(User, user.id)
24
+ Rails.cache.read(key[:key]).should_not be_nil
25
+ user.expire_all
26
+ Rails.cache.read(key[:key]).should be_nil
27
+ end
28
+
29
+ it "should delete with_attribute cache" do
30
+ user = User.find_cached_by_login("flyerhzm")
31
+ key = GenCache.attribute_key(User, :login, "flyerhzm")
32
+ Rails.cache.read(key[:key]).should == {:class => user.class, 'attributes' => user.attributes}
33
+ user.expire_all
34
+ Rails.cache.read(key[:key]).should be_nil
35
+ end
36
+
37
+ it "should delete with_method cache" do
38
+ user.cached_last_post
39
+ key = GenCache.method_key(user, :last_post)
40
+ Rails.cache.read(key[:key]).should_not be_nil
41
+ user.update_attribute(:login, "pathouse")
42
+ key = GenCache.method_key(user, :last_post)
43
+ Rails.cache.read(key[:key]).should be_nil
44
+ end
45
+
46
+ it "should delete with_class_method cache (default_post)" do
47
+ Post.cached_default_post
48
+ key = GenCache.class_method_key(Post, :default_post)
49
+ Rails.cache.read(key[:key]).should_not be_nil
50
+ @post1.expire_all
51
+ Rails.cache.read(key[:key]).should be_nil
52
+ end
53
+
54
+ it "should delete with_class_method cache (retrieve_with_user_id)" do
55
+ Post.cached_retrieve_with_user_id(1)
56
+ key = GenCache.class_method_key(Post, :retrieve_with_user_id)
57
+ Rails.cache.read(key[:key]).should_not be_nil
58
+ @post1.expire_all
59
+ Rails.cache.read(key[:key]).should be_nil
60
+ end
61
+
62
+ it "should delete with_class_method cache (retrieve_with_user_id) with different arguments" do
63
+ Post.cached_retrieve_with_user_id(1)
64
+ Post.cached_retrieve_with_user_id(2)
65
+ key = GenCache.class_method_key(Post, :retrieve_with_user_id)
66
+ Rails.cache.read(key[:key]).should_not be_nil
67
+ @post1.expire_all
68
+ Rails.cache.read(key[:key]).should be_nil
69
+ end
70
+
71
+ it "should delete with_class_method cache (retrieve_with_both)" do
72
+ Post.cached_retrieve_with_both(1, 1)
73
+ key = GenCache.class_method_key(Post, :retrieve_with_both)
74
+ Rails.cache.read(key[:key]).should_not be_nil
75
+ @post1.expire_all
76
+ Rails.cache.read(key[:key]).should be_nil
77
+ end
78
+
79
+ it "should delete associations cache" do
80
+ user.cached_images
81
+ key = GenCache.association_key(user, :images)
82
+ Rails.cache.read(key[:key]).should_not be_nil
83
+ user.update_attribute(:login, 'pathouse')
84
+ key = GenCache.association_key(user, :images)
85
+ Rails.cache.read(key[:key]).should == []
86
+ end
87
+ end
88
+
89
+ context "single table inheritance bug" do
90
+ context "user" do
91
+ it "has cached indices" do
92
+ User.cached_indices.should_not be_nil
93
+ end
94
+
95
+ it "has specific cached indices" do
96
+ User.cached_indices.keys.should include :login
97
+ User.cached_indices.keys.should_not include :email
98
+ end
99
+
100
+ it "should have cached_methods" do
101
+ User.cached_methods.should_not be_nil
102
+ User.cached_methods.should == [:last_post, :bad_iv_name!, :bad_iv_name?]
103
+ end
104
+ end
105
+
106
+ context "expiring class_method cache" do
107
+ it "expires correctly from inherited attributes" do
108
+ key = GenCache.class_method_key(User, :default_name)
109
+ Rails.cache.read(key[:key]).should be_nil
110
+ User.cached_default_name
111
+ Rails.cache.read(key[:key]).should == "flyerhzm"
112
+ user.expire_all
113
+ Rails.cache.read(key[:key]).should be_nil
114
+ end
115
+ end
116
+
117
+ context "descendant" do
118
+
119
+ it "should have cached indices hash" do
120
+ Descendant.cached_indices.should_not be_nil
121
+ end
122
+
123
+ it "has specific cached indices" do
124
+ Descendant.cached_indices.keys.should include :login
125
+ Descendant.cached_indices.keys.should include :email
126
+ end
127
+
128
+ it "should have cached_methods" do
129
+ Descendant.cached_methods.should_not be_nil
130
+ Descendant.cached_methods.should == [:last_post, :bad_iv_name!, :bad_iv_name?, :name]
131
+ end
132
+
133
+ context "expiring method cache" do
134
+ it "expires correctly from inherited attributes" do
135
+ key = GenCache.method_key(descendant, :last_post)
136
+ Rails.cache.read(key[:key]).should be_nil
137
+ descendant.cached_last_post.should == descendant.last_post
138
+ Rails.cache.read(key[:key]).should == {:class => descendant.last_post.class, 'attributes' => descendant.last_post.attributes}
139
+ descendant.update_attribute(:login, 'pathouse')
140
+ key = GenCache.method_key(descendant, :last_post)
141
+ Rails.cache.read(key[:key]).should be_nil
142
+ end
143
+ end
144
+
145
+ context "expiring attribute cache" do
146
+ it "expires correctly from inherited attributes" do
147
+ descendant.update_attribute(:login, "scotterc")
148
+ key = GenCache.attribute_key(Descendant, :login, "scotterc")
149
+ Rails.cache.read(key[:key]).should be_nil
150
+ Descendant.find_cached_by_login("scotterc").should == descendant
151
+ Rails.cache.read(key[:key]).should == {:class => descendant.class, 'attributes' => descendant.attributes}
152
+ descendant.expire_all
153
+ Rails.cache.read(key[:key]).should be_nil
154
+ end
155
+ end
156
+
157
+ context "expiring association cache" do
158
+ it "expires correctly from inherited attributes" do
159
+ key = GenCache.association_key(descendant, :posts)
160
+ Rails.cache.read(key[:key]).should be_nil
161
+ descendant.cached_posts.should == [@post3]
162
+ Rails.cache.read(key[:key]).should == [GenCache.instance_key(Post, @post3.id)]
163
+ descendant.update_attribute(:login, "pathouse")
164
+ key = GenCache.association_key(descendant, :posts)
165
+ Rails.cache.read(key[:key]).should be_nil
166
+ end
167
+ end
168
+
169
+ context "expiring class_method cache" do
170
+ it "expires correctly from inherited attributes" do
171
+ key = GenCache.class_method_key(Descendant, :default_name)
172
+ Rails.cache.read(key[:key]).should be_nil
173
+ Descendant.cached_default_name
174
+ Rails.cache.read(key[:key]).should == "ScotterC"
175
+ descendant.expire_all
176
+ Rails.cache.read(key[:key]).should be_nil
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ end