cached-models 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +84 -0
- data/MIT-LICENSE +20 -0
- data/README +95 -0
- data/Rakefile +81 -0
- data/about.yml +8 -0
- data/cached-models.gemspec +19 -0
- data/init.rb +2 -0
- data/install.rb +1 -0
- data/lib/activerecord/lib/active_record/associations/association_collection.rb +95 -0
- data/lib/activerecord/lib/active_record/associations/association_proxy.rb +39 -0
- data/lib/activerecord/lib/active_record/associations/has_many_association.rb +7 -0
- data/lib/activerecord/lib/active_record/associations.rb +379 -0
- data/lib/activerecord/lib/active_record/base.rb +69 -0
- data/lib/activerecord/lib/active_record.rb +4 -0
- data/lib/cached-models.rb +1 -0
- data/lib/cached_models.rb +4 -0
- data/setup.rb +1585 -0
- data/tasks/cached_models_tasks.rake +90 -0
- data/test/active_record/associations/has_many_association_test.rb +401 -0
- data/test/active_record/base_test.rb +32 -0
- data/test/fixtures/authors.yml +13 -0
- data/test/fixtures/blogs.yml +7 -0
- data/test/fixtures/comments.yml +19 -0
- data/test/fixtures/posts.yml +23 -0
- data/test/fixtures/tags.yml +14 -0
- data/test/models/author.rb +10 -0
- data/test/models/blog.rb +4 -0
- data/test/models/comment.rb +3 -0
- data/test/models/post.rb +7 -0
- data/test/models/tag.rb +3 -0
- data/test/test_helper.rb +42 -0
- data/uninstall.rb +1 -0
- metadata +105 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'active_record/fixtures'
|
4
|
+
|
5
|
+
path_to_fixtures = File.dirname(__FILE__) + '/../test/fixtures'
|
6
|
+
fixtures = %w( authors blogs posts comments tags )
|
7
|
+
|
8
|
+
desc 'Run default task (test)'
|
9
|
+
task :cached_models => 'cached_models:test'
|
10
|
+
|
11
|
+
namespace :cached_models do
|
12
|
+
desc 'Reset the CachedModels data'
|
13
|
+
task :reset => [ :teardown, :setup ]
|
14
|
+
|
15
|
+
desc 'Create CachedModels test database tables and load fixtures'
|
16
|
+
task :setup => [ :create_tables, :load_fixtures ]
|
17
|
+
|
18
|
+
desc 'Remove all CachedModels data'
|
19
|
+
task :teardown => :drop_tables
|
20
|
+
|
21
|
+
desc 'Create CachedModels test database tables'
|
22
|
+
task :create_tables => :environment do
|
23
|
+
ActiveRecord::Schema.define do
|
24
|
+
create_table :authors, :force => true do |t|
|
25
|
+
t.integer :blog_id
|
26
|
+
t.string :first_name
|
27
|
+
t.string :last_name
|
28
|
+
t.integer :age
|
29
|
+
|
30
|
+
t.timestamps
|
31
|
+
end
|
32
|
+
|
33
|
+
create_table :blogs, :force => true do |t|
|
34
|
+
t.string :title
|
35
|
+
|
36
|
+
t.timestamps
|
37
|
+
end
|
38
|
+
|
39
|
+
create_table :posts, :force => true do |t|
|
40
|
+
t.integer :author_id
|
41
|
+
t.integer :blog_id
|
42
|
+
t.string :title
|
43
|
+
t.text :text
|
44
|
+
t.datetime :published_at
|
45
|
+
|
46
|
+
t.timestamps
|
47
|
+
end
|
48
|
+
|
49
|
+
create_table :comments, :force => true do |t|
|
50
|
+
t.integer :post_id
|
51
|
+
t.string :email
|
52
|
+
t.text :text
|
53
|
+
|
54
|
+
t.timestamps
|
55
|
+
end
|
56
|
+
|
57
|
+
create_table :tags, :force => true do |t|
|
58
|
+
t.integer :taggable_id
|
59
|
+
t.string :taggable_type
|
60
|
+
t.string :name
|
61
|
+
|
62
|
+
t.timestamps
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
desc 'Drops CachedModels test database tables'
|
68
|
+
task :drop_tables => :environment do
|
69
|
+
ActiveRecord::Base.connection.drop_table :authors
|
70
|
+
ActiveRecord::Base.connection.drop_table :posts
|
71
|
+
ActiveRecord::Base.connection.drop_table :comments
|
72
|
+
ActiveRecord::Base.connection.drop_table :tags
|
73
|
+
end
|
74
|
+
|
75
|
+
desc 'Load fixtures'
|
76
|
+
task :load_fixtures => :environment do
|
77
|
+
fixtures.each { |f| Fixtures.create_fixtures(path_to_fixtures, f) }
|
78
|
+
end
|
79
|
+
|
80
|
+
desc 'Test CachedModels'
|
81
|
+
task :test => [ :setup, 'test:all' ]
|
82
|
+
|
83
|
+
namespace :test do
|
84
|
+
desc 'Run CachedModels tests'
|
85
|
+
Rake::TestTask.new(:all) do |t|
|
86
|
+
t.test_files = FileList["#{File.dirname( __FILE__ )}/../test/**/*_test.rb"]
|
87
|
+
t.verbose = true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,401 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
2
|
+
require 'active_record/associations/has_many_association'
|
3
|
+
|
4
|
+
class HasManyAssociationTest < Test::Unit::TestCase
|
5
|
+
include ActiveRecord::Associations
|
6
|
+
|
7
|
+
def setup
|
8
|
+
cache.clear rescue nil
|
9
|
+
end
|
10
|
+
|
11
|
+
uses_mocha 'HasManyAssociationTest' do
|
12
|
+
def test_should_always_use_cache_for_all_instances_which_reference_the_same_record
|
13
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
14
|
+
expected = authors(:luca).cached_posts
|
15
|
+
actual = Author.first.cached_posts
|
16
|
+
assert_equal expected, actual
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_expire_cache_on_update
|
20
|
+
author = authors(:luca)
|
21
|
+
old_cache_key = author.cache_key
|
22
|
+
|
23
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
24
|
+
cache.expects(:delete).with("#{cache_key}/cached_posts").returns true
|
25
|
+
|
26
|
+
author.cached_posts # force cache loading
|
27
|
+
author.update_attributes :first_name => author.first_name.upcase
|
28
|
+
|
29
|
+
# assert_not_equal old_cache_key, author.cache_key
|
30
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_should_not_expire_cache_on_update_on_missing_updated_at
|
34
|
+
author = authors(:luca)
|
35
|
+
old_cache_key = author.cache_key
|
36
|
+
|
37
|
+
author.stubs(:[]).with(:updated_at).returns nil
|
38
|
+
author.expects(:[]).with('blog_id').returns author.blog_id
|
39
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
40
|
+
cache.expects(:delete).with("#{cache_key}/cached_posts").never
|
41
|
+
cache.expects(:delete).with("#{cache_key}/cached_comments").never
|
42
|
+
cache.expects(:delete).with("#{cache_key}/cached_posts_with_comments").never
|
43
|
+
|
44
|
+
author.cached_posts # force cache loading
|
45
|
+
author.update_attributes :first_name => author.first_name.upcase
|
46
|
+
|
47
|
+
# assert_not_equal old_cache_key, author.cache_key
|
48
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_should_use_cache_when_find_with_scope
|
52
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").returns association_proxy
|
53
|
+
|
54
|
+
post = authors(:luca).cached_posts.find(posts(:welcome).id)
|
55
|
+
assert_equal posts(:welcome), post
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_should_use_cache_when_find_with_scope_using_multiple_ids
|
59
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").returns association_proxy
|
60
|
+
|
61
|
+
ids = posts_by_author(:luca).map(&:id)
|
62
|
+
assert_equal posts_by_author(:luca),
|
63
|
+
authors(:luca).cached_posts.find(ids)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_should_use_cache_when_fetch_first_from_collection
|
67
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").returns association_proxy
|
68
|
+
# cache.expects(:read).with("#{cache_key}/cached_posts").returns posts_by_author(:luca)
|
69
|
+
|
70
|
+
assert_equal [ posts_by_author(:luca).first ],
|
71
|
+
authors(:luca).cached_posts.first(1)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_should_use_cache_when_fetch_last_from_collection
|
75
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").returns association_proxy
|
76
|
+
# cache.expects(:read).with("#{cache_key}/cached_posts").returns posts_by_author(:luca)
|
77
|
+
|
78
|
+
assert_equal [ posts_by_author(:luca).last ],
|
79
|
+
authors(:luca).cached_posts.last(1)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_should_use_cache_when_reset_collection
|
83
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
84
|
+
|
85
|
+
assert_false authors(:luca).cached_posts.reset
|
86
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_should_expire_cache_when_delete_all_elements_from_collection
|
90
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
91
|
+
# cache.expects(:read).with("#{cache_key}/cached_posts").returns posts_by_author(:luca)
|
92
|
+
|
93
|
+
authors(:luca).cached_posts.delete_all
|
94
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_should_expire_cache_when_destroy_all_elements_from_collection
|
98
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
99
|
+
# cache.expects(:read).with("#{cache_key}/cached_posts").returns posts_by_author(:luca)
|
100
|
+
|
101
|
+
authors(:luca).cached_posts.destroy_all
|
102
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_should_use_cache_on_collection_sum
|
106
|
+
cache.expects(:fetch).with("#{blogs(:weblog).cache_key}/authors").returns authors_association_proxy
|
107
|
+
|
108
|
+
assert_equal authors_by_blog(:weblog).map(&:age).sum,
|
109
|
+
blogs(:weblog).authors.sum(:age)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_should_not_use_cache_on_false_cached_option
|
113
|
+
cache.expects(:fetch).never
|
114
|
+
authors(:luca).posts
|
115
|
+
authors(:luca).posts(true) # force reload
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_should_cache_associated_objects
|
119
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns(posts_by_author(:luca))
|
120
|
+
|
121
|
+
posts = authors(:luca).cached_posts
|
122
|
+
assert_equal posts, authors(:luca).cached_posts
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_should_reload_association_and_refresh_the_cache_on_force_reload
|
126
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns(posts_by_author(:luca))
|
127
|
+
|
128
|
+
reloaded_posts = authors(:luca).cached_posts(true)
|
129
|
+
assert_equal reloaded_posts, authors(:luca).cached_posts
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_should_cache_associated_ids
|
133
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
134
|
+
cache.expects(:fetch).with("#{cache_key}/cached_post_ids").times(2).returns(posts_by_author(:luca).map(&:id))
|
135
|
+
ids = authors(:luca).cached_post_ids
|
136
|
+
assert_equal ids, authors(:luca).cached_post_ids
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_should_not_cache_associated_ids_on_false_cached_option
|
140
|
+
cache.expects(:fetch).never
|
141
|
+
authors(:luca).post_ids
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_should_cache_all_eager_loaded_objects
|
145
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts_with_comments").times(2).returns(posts_by_author(:luca, true))
|
146
|
+
posts = authors(:luca).cached_posts_with_comments
|
147
|
+
assert_equal posts, authors(:luca).cached_posts_with_comments
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_should_not_cache_eager_loaded_objects_on_false_cached_option
|
151
|
+
cache.expects(:fetch).never
|
152
|
+
authors(:luca).posts_with_comments
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_should_cache_polymorphic_associations
|
156
|
+
cache.expects(:fetch).with("#{posts(:cached_models).cache_key}/cached_tags").times(2).returns(tags_by_post(:cached_models))
|
157
|
+
tags = posts(:cached_models).cached_tags
|
158
|
+
assert_equal tags, posts(:cached_models).cached_tags
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_should_not_cache_polymorphic_associations_on_false_cached_option
|
162
|
+
cache.expects(:fetch).never
|
163
|
+
posts(:cached_models).tags
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_should_cache_habtm_associations
|
167
|
+
cache.expects(:fetch).with("#{cache_key}/cached_comments").times(2).returns(comments_by_author(:luca))
|
168
|
+
comments = authors(:luca).cached_comments
|
169
|
+
assert_equal comments, authors(:luca).cached_comments
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_should_not_cache_habtm_associations_on_false_cached_option
|
173
|
+
cache.expects(:fetch).never
|
174
|
+
authors(:luca).comments
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_should_refresh_cache_when_associated_elements_change
|
178
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
179
|
+
|
180
|
+
post = authors(:luca).cached_posts.last # force cache loading and fetch a post
|
181
|
+
post.update_attributes :title => 'Cached Models!'
|
182
|
+
|
183
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_should_refresh_cache_when_pushing_element_to_association
|
187
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
188
|
+
cache.expects(:write).with("#{cache_key}/cached_posts", association_proxy).returns true
|
189
|
+
|
190
|
+
post = create_post :author_id => nil
|
191
|
+
authors(:luca).cached_posts << post
|
192
|
+
|
193
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_should_refresh_caches_when_pushing_element_to_association_belonging_to_another_model
|
197
|
+
cache.expects(:fetch).with("#{authors(:chuck).cache_key}/cached_posts").times(2).returns association_proxy(:chuck)
|
198
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
199
|
+
|
200
|
+
post = authors(:chuck).cached_posts.last
|
201
|
+
authors(:luca).cached_posts << post
|
202
|
+
|
203
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
204
|
+
assert_equal posts_by_author(:chuck), authors(:chuck).cached_posts
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_should_refresh_caches_when_pushing_element_to_polymorphic_association_belonging_to_another_model
|
208
|
+
cache.expects(:fetch).with("#{posts(:welcome).cache_key}/cached_tags").times(2).returns tags_association_proxy
|
209
|
+
cache.expects(:fetch).with("#{posts(:cached_models).cache_key}/cached_tags").times(2).returns tags_association_proxy(:cached_models)
|
210
|
+
tag = posts(:welcome).cached_tags.last
|
211
|
+
|
212
|
+
posts(:cached_models).cached_tags << tag
|
213
|
+
|
214
|
+
# NOTE for some weird reason the assertion fails, even if the collections are equals.
|
215
|
+
# I forced the comparision between the ids.
|
216
|
+
assert_equal tags_by_post(:cached_models).map(&:id).sort,
|
217
|
+
posts(:cached_models).cached_tags.map(&:id).sort
|
218
|
+
assert_equal tags_by_post(:welcome), posts(:welcome).cached_tags
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_should_not_use_cache_when_pushing_element_to_association_on_false_cached_option
|
222
|
+
cache.expects(:write).never
|
223
|
+
|
224
|
+
post = create_post :author_id => nil
|
225
|
+
authors(:luca).posts << post
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_should_not_use_cache_when_pushing_element_to_association_belonging_to_anotner_model_on_false_cached_option
|
229
|
+
cache.expects(:delete).with("#{blogs(:weblog).cache_key}/posts").never
|
230
|
+
post = blogs(:weblog).posts.last
|
231
|
+
blogs(:blog).posts << post
|
232
|
+
|
233
|
+
assert_equal posts_by_blog(:blog), blogs(:blog).posts
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_should_not_use_cache_when_pushing_element_to_polymorphic_association_belonging_to_another_model_on_false_cached_option
|
237
|
+
cache.expects(:delete).never
|
238
|
+
tag = posts(:welcome).tags.last
|
239
|
+
posts(:cached_models).tags << tag
|
240
|
+
|
241
|
+
assert_equal tags_by_post(:cached_models), posts(:cached_models).tags
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_should_update_cache_when_pushing_element_with_build
|
245
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
246
|
+
|
247
|
+
author = authors(:luca)
|
248
|
+
post = author.cached_posts.build post_options
|
249
|
+
post.save
|
250
|
+
|
251
|
+
assert_equal posts_by_author(:luca), author.cached_posts
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_should_update_cache_when_pushing_element_with_create
|
255
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
256
|
+
|
257
|
+
author = authors(:luca)
|
258
|
+
author.cached_posts.create post_options(:title => "CM Overview")
|
259
|
+
|
260
|
+
assert_equal posts_by_author(:luca), author.cached_posts
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_should_update_cache_when_pushing_element_with_create_bang_method
|
264
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
265
|
+
|
266
|
+
author = authors(:luca)
|
267
|
+
author.cached_posts.create! post_options(:title => "CM Overview!!")
|
268
|
+
|
269
|
+
assert_equal posts_by_author(:luca), author.cached_posts
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_should_update_cache_when_deleting_element_from_collection
|
273
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
274
|
+
|
275
|
+
authors(:luca).cached_posts.delete(posts_by_author(:luca).first)
|
276
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_should_update_cache_when_clearing_collection
|
280
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
281
|
+
authors(:luca).cached_posts.clear
|
282
|
+
|
283
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_should_update_cache_when_clearing_collection_with_dependent_destroy_option
|
287
|
+
cache.expects(:fetch).with("#{cache_key}/cached_dependent_posts").times(2).returns association_proxy
|
288
|
+
authors(:luca).cached_dependent_posts.clear
|
289
|
+
|
290
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_dependent_posts
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_should_update_cache_when_directly_assigning_a_new_collection
|
294
|
+
posts = [ posts_by_author(:luca).first ]
|
295
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
296
|
+
authors(:luca).cached_posts = posts
|
297
|
+
|
298
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
299
|
+
end
|
300
|
+
|
301
|
+
def test_should_update_cache_when_replace_collection
|
302
|
+
post = create_post; post.save
|
303
|
+
posts = [ posts_by_author(:luca).first, post ]
|
304
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
305
|
+
authors(:luca).cached_posts.replace(posts)
|
306
|
+
|
307
|
+
assert_equal posts_by_author(:luca), authors(:luca).cached_posts
|
308
|
+
end
|
309
|
+
|
310
|
+
def test_should_use_cache_for_collection_size
|
311
|
+
# cache.expects(:fetch).with("#{cache_key}/cached_posts").times(2).returns association_proxy
|
312
|
+
|
313
|
+
assert_equal posts_by_author(:luca).size,
|
314
|
+
authors(:luca).cached_posts.size
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_should_use_cache_for_collection_length
|
318
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").returns association_proxy
|
319
|
+
|
320
|
+
assert_equal posts_by_author(:luca).length,
|
321
|
+
authors(:luca).cached_posts.length
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_should_use_cache_for_collection_empty
|
325
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").returns association_proxy
|
326
|
+
|
327
|
+
assert_equal posts_by_author(:luca).empty?,
|
328
|
+
authors(:luca).cached_posts.empty?
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_should_use_cache_for_collection_any
|
332
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").returns association_proxy
|
333
|
+
|
334
|
+
assert_equal posts_by_author(:luca).any?,
|
335
|
+
authors(:luca).cached_posts.any?
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_should_use_cache_for_collection_include
|
339
|
+
cache.expects(:fetch).with("#{cache_key}/cached_posts").returns association_proxy
|
340
|
+
|
341
|
+
post = posts_by_author(:luca).first
|
342
|
+
assert authors(:luca).cached_posts.include?(post)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
private
|
347
|
+
def posts_by_author(author, include_comments = false)
|
348
|
+
conditions = include_comments ? { :include => :comments } : { }
|
349
|
+
Post.find_all_by_author_id(authors(author).id, conditions)
|
350
|
+
end
|
351
|
+
|
352
|
+
def posts_by_blog(blog)
|
353
|
+
Post.find_all_by_blog_id(blogs(blog).id)
|
354
|
+
end
|
355
|
+
|
356
|
+
def tags_by_post(post)
|
357
|
+
Tag.find_all_by_taggable_id(posts(post).id)
|
358
|
+
end
|
359
|
+
|
360
|
+
def comments_by_author(author)
|
361
|
+
Comment.find(:all, :conditions => ["post_id IN (?)", authors(author).post_ids])
|
362
|
+
end
|
363
|
+
|
364
|
+
def authors_by_blog(blog)
|
365
|
+
Author.find_all_by_blog_id(blogs(blog).id)
|
366
|
+
end
|
367
|
+
|
368
|
+
def association_proxy(author = :luca)
|
369
|
+
HasManyAssociation.new(authors(author), Author.reflect_on_association(:cached_posts))
|
370
|
+
end
|
371
|
+
|
372
|
+
def authors_association_proxy(blog = :weblog)
|
373
|
+
HasManyAssociation.new(blogs(blog), Blog.reflect_on_association(:authors))
|
374
|
+
end
|
375
|
+
|
376
|
+
def tags_association_proxy(post = :welcome)
|
377
|
+
HasManyAssociation.new(posts(post), Post.reflect_on_association(:cached_tags))
|
378
|
+
end
|
379
|
+
|
380
|
+
def comments_association_proxy(author = :luca)
|
381
|
+
HasManyThroughAssociation.new(authors(author), Author.reflect_on_association(:cached_comments))
|
382
|
+
end
|
383
|
+
|
384
|
+
def create_post(options = {})
|
385
|
+
Post.new({ :author_id => 1,
|
386
|
+
:title => 'CachedModels',
|
387
|
+
:text => 'Introduction to CachedModels plugin',
|
388
|
+
:published_at => 1.week.ago }.merge(options))
|
389
|
+
end
|
390
|
+
|
391
|
+
def post_options(options = {})
|
392
|
+
{ :blog_id => blogs(:weblog).id,
|
393
|
+
:title => "Cached models review",
|
394
|
+
:text => "Cached models review..",
|
395
|
+
:published_at => 1.week.ago }.merge(options)
|
396
|
+
end
|
397
|
+
|
398
|
+
def cache_key
|
399
|
+
@cache_key ||= authors(:luca).cache_key
|
400
|
+
end
|
401
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class BaseTest < Test::Unit::TestCase
|
4
|
+
fixtures :authors
|
5
|
+
|
6
|
+
def test_should_have_cache
|
7
|
+
assert_equal RAILS_CACHE, ActiveRecord::Base.rails_cache if defined? Rails
|
8
|
+
assert_kind_of ActiveSupport::Cache::Store, ActiveRecord::Base.rails_cache
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_should_wrap_rails_cache
|
12
|
+
assert_equal RAILS_CACHE, Post.new.send(:rails_cache) if defined? Rails
|
13
|
+
assert_kind_of ActiveSupport::Cache::Store, Post.new.send(:rails_cache)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_reflection_cache_key
|
17
|
+
author = authors(:luca)
|
18
|
+
actual = author.send(:reflection_cache_key, Author.reflections[:cached_posts])
|
19
|
+
assert_equal "#{author.cache_key}/cached_posts", actual
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_cached_association
|
23
|
+
author = authors(:luca)
|
24
|
+
assert_equal({}, author.send(:cached_associations))
|
25
|
+
|
26
|
+
author.cached_posts # force cache loading
|
27
|
+
assert_equal({:cached_posts => true}, author.send(:cached_associations))
|
28
|
+
|
29
|
+
author.send(:cache_delete, Author.reflections[:cached_posts])
|
30
|
+
assert_equal({:cached_posts => false}, author.send(:cached_associations))
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
comment:
|
2
|
+
post_id: 1
|
3
|
+
email: john@doe.com
|
4
|
+
text: Good luck for your blog.
|
5
|
+
|
6
|
+
positive_comment:
|
7
|
+
post_id: 2
|
8
|
+
email: john@doe.com
|
9
|
+
text: Very nice plugin, thank you!
|
10
|
+
|
11
|
+
negative_comment:
|
12
|
+
post_id: 2
|
13
|
+
email: doe@john.com
|
14
|
+
text: Crappy stuff!
|
15
|
+
|
16
|
+
comment_for_fight_club:
|
17
|
+
post_id: 3
|
18
|
+
email: john@doe.com
|
19
|
+
text: Awsome book!
|
@@ -0,0 +1,23 @@
|
|
1
|
+
welcome:
|
2
|
+
id: 1
|
3
|
+
blog_id: 1
|
4
|
+
author_id: 1
|
5
|
+
title: Welcome
|
6
|
+
text: Welcome to my blog
|
7
|
+
published_at: <%= 3.years.ago %>
|
8
|
+
|
9
|
+
cached_models:
|
10
|
+
id: 2
|
11
|
+
blog_id: 1
|
12
|
+
author_id: 1
|
13
|
+
title: Cached Models
|
14
|
+
text: Cached Models plugin overview
|
15
|
+
published_at: <%= 2.weeks.ago %>
|
16
|
+
|
17
|
+
fight_club:
|
18
|
+
id: 3
|
19
|
+
blog_id: 2
|
20
|
+
author_id: 2
|
21
|
+
title: Fight Club
|
22
|
+
text: This is a Fight Club review
|
23
|
+
published_at: <%= 1.week.ago %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
announcements_on_welcome:
|
2
|
+
taggable_id: 1
|
3
|
+
taggable_type: Post
|
4
|
+
name: announcements
|
5
|
+
|
6
|
+
plugin_on_cached_models:
|
7
|
+
taggable_id: 2
|
8
|
+
taggable_type: Post
|
9
|
+
name: plugin
|
10
|
+
|
11
|
+
rails_on_cached_models:
|
12
|
+
taggable_id: 2
|
13
|
+
taggable_type: Post
|
14
|
+
name: rails
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Author < ActiveRecord::Base
|
2
|
+
belongs_to :blog, :cached => true
|
3
|
+
has_many :posts
|
4
|
+
has_many :cached_posts, :cached => true, :class_name => 'Post'
|
5
|
+
has_many :cached_dependent_posts, :cached => true, :class_name => 'Post', :dependent => :destroy
|
6
|
+
has_many :posts_with_comments, :class_name => 'Post', :include => :comments
|
7
|
+
has_many :cached_posts_with_comments, :class_name => 'Post', :include => :comments, :cached => true
|
8
|
+
has_many :comments, :through => :posts
|
9
|
+
has_many :cached_comments, :through => :posts, :source => :comments, :cached => true
|
10
|
+
end
|
data/test/models/blog.rb
ADDED
data/test/models/post.rb
ADDED
data/test/models/tag.rb
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'active_support'
|
6
|
+
require 'action_controller'
|
7
|
+
require 'active_support/test_case'
|
8
|
+
require 'active_record/fixtures'
|
9
|
+
require 'action_controller/integration'
|
10
|
+
|
11
|
+
# FIXME load path
|
12
|
+
require File.dirname(__FILE__) + '/../../../../config/environment'
|
13
|
+
$:.unshift File.dirname(__FILE__) + '/models'
|
14
|
+
require 'author'
|
15
|
+
require 'post'
|
16
|
+
|
17
|
+
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures"
|
18
|
+
ActionController::IntegrationTest.fixture_path = Test::Unit::TestCase.fixture_path
|
19
|
+
|
20
|
+
class Test::Unit::TestCase
|
21
|
+
self.use_transactional_fixtures = true
|
22
|
+
self.use_instantiated_fixtures = false
|
23
|
+
fixtures :all
|
24
|
+
|
25
|
+
# Assert the given condition is false
|
26
|
+
def assert_false(condition, message = nil)
|
27
|
+
assert !condition, message
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def cache
|
32
|
+
ActiveRecord::Base.rails_cache
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def uses_mocha(description)
|
37
|
+
require 'rubygems'
|
38
|
+
require 'mocha'
|
39
|
+
yield
|
40
|
+
rescue LoadError
|
41
|
+
$stderr.puts "Skipping #{description} tests. `gem install mocha` and try again."
|
42
|
+
end
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|