cached-models 0.0.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/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
|