bullet_instructure 4.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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +20 -0
  6. data/CHANGELOG.md +75 -0
  7. data/Gemfile +19 -0
  8. data/Gemfile.mongoid +14 -0
  9. data/Gemfile.mongoid-2.4 +19 -0
  10. data/Gemfile.mongoid-2.5 +19 -0
  11. data/Gemfile.mongoid-2.6 +19 -0
  12. data/Gemfile.mongoid-2.7 +19 -0
  13. data/Gemfile.mongoid-2.8 +19 -0
  14. data/Gemfile.mongoid-3.0 +19 -0
  15. data/Gemfile.mongoid-3.1 +19 -0
  16. data/Gemfile.mongoid-4.0 +19 -0
  17. data/Gemfile.rails-3.0 +19 -0
  18. data/Gemfile.rails-3.1 +19 -0
  19. data/Gemfile.rails-3.2 +19 -0
  20. data/Gemfile.rails-4.0 +19 -0
  21. data/Gemfile.rails-4.1 +19 -0
  22. data/Guardfile +8 -0
  23. data/Hacking.md +74 -0
  24. data/MIT-LICENSE +20 -0
  25. data/README.md +428 -0
  26. data/Rakefile +52 -0
  27. data/bullet_instructure.gemspec +27 -0
  28. data/lib/bullet.rb +196 -0
  29. data/lib/bullet/active_record3.rb +148 -0
  30. data/lib/bullet/active_record3x.rb +128 -0
  31. data/lib/bullet/active_record4.rb +128 -0
  32. data/lib/bullet/active_record41.rb +121 -0
  33. data/lib/bullet/dependency.rb +81 -0
  34. data/lib/bullet/detector.rb +9 -0
  35. data/lib/bullet/detector/association.rb +67 -0
  36. data/lib/bullet/detector/base.rb +6 -0
  37. data/lib/bullet/detector/counter_cache.rb +59 -0
  38. data/lib/bullet/detector/n_plus_one_query.rb +89 -0
  39. data/lib/bullet/detector/unused_eager_loading.rb +84 -0
  40. data/lib/bullet/ext/object.rb +9 -0
  41. data/lib/bullet/ext/string.rb +5 -0
  42. data/lib/bullet/mongoid2x.rb +56 -0
  43. data/lib/bullet/mongoid3x.rb +56 -0
  44. data/lib/bullet/mongoid4x.rb +56 -0
  45. data/lib/bullet/notification.rb +10 -0
  46. data/lib/bullet/notification/base.rb +97 -0
  47. data/lib/bullet/notification/counter_cache.rb +13 -0
  48. data/lib/bullet/notification/n_plus_one_query.rb +28 -0
  49. data/lib/bullet/notification/unused_eager_loading.rb +13 -0
  50. data/lib/bullet/notification_collector.rb +24 -0
  51. data/lib/bullet/rack.rb +81 -0
  52. data/lib/bullet/registry.rb +7 -0
  53. data/lib/bullet/registry/association.rb +13 -0
  54. data/lib/bullet/registry/base.rb +40 -0
  55. data/lib/bullet/registry/object.rb +13 -0
  56. data/lib/bullet/version.rb +4 -0
  57. data/perf/benchmark.rb +121 -0
  58. data/rails/init.rb +1 -0
  59. data/spec/bullet/detector/association_spec.rb +26 -0
  60. data/spec/bullet/detector/base_spec.rb +8 -0
  61. data/spec/bullet/detector/counter_cache_spec.rb +56 -0
  62. data/spec/bullet/detector/n_plus_one_query_spec.rb +138 -0
  63. data/spec/bullet/detector/unused_eager_loading_spec.rb +88 -0
  64. data/spec/bullet/ext/object_spec.rb +17 -0
  65. data/spec/bullet/ext/string_spec.rb +13 -0
  66. data/spec/bullet/notification/base_spec.rb +83 -0
  67. data/spec/bullet/notification/counter_cache_spec.rb +12 -0
  68. data/spec/bullet/notification/n_plus_one_query_spec.rb +14 -0
  69. data/spec/bullet/notification/unused_eager_loading_spec.rb +12 -0
  70. data/spec/bullet/notification_collector_spec.rb +32 -0
  71. data/spec/bullet/rack_spec.rb +97 -0
  72. data/spec/bullet/registry/association_spec.rb +26 -0
  73. data/spec/bullet/registry/base_spec.rb +44 -0
  74. data/spec/bullet/registry/object_spec.rb +24 -0
  75. data/spec/bullet_spec.rb +41 -0
  76. data/spec/integration/active_record3/association_spec.rb +651 -0
  77. data/spec/integration/active_record4/association_spec.rb +649 -0
  78. data/spec/integration/counter_cache_spec.rb +63 -0
  79. data/spec/integration/mongoid/association_spec.rb +258 -0
  80. data/spec/models/address.rb +3 -0
  81. data/spec/models/author.rb +3 -0
  82. data/spec/models/base_user.rb +5 -0
  83. data/spec/models/category.rb +7 -0
  84. data/spec/models/city.rb +3 -0
  85. data/spec/models/client.rb +4 -0
  86. data/spec/models/comment.rb +4 -0
  87. data/spec/models/company.rb +3 -0
  88. data/spec/models/country.rb +3 -0
  89. data/spec/models/document.rb +5 -0
  90. data/spec/models/entry.rb +3 -0
  91. data/spec/models/firm.rb +4 -0
  92. data/spec/models/folder.rb +2 -0
  93. data/spec/models/mongoid/address.rb +7 -0
  94. data/spec/models/mongoid/category.rb +8 -0
  95. data/spec/models/mongoid/comment.rb +7 -0
  96. data/spec/models/mongoid/company.rb +7 -0
  97. data/spec/models/mongoid/entry.rb +7 -0
  98. data/spec/models/mongoid/post.rb +12 -0
  99. data/spec/models/mongoid/user.rb +5 -0
  100. data/spec/models/newspaper.rb +3 -0
  101. data/spec/models/page.rb +2 -0
  102. data/spec/models/person.rb +3 -0
  103. data/spec/models/pet.rb +3 -0
  104. data/spec/models/post.rb +10 -0
  105. data/spec/models/relationship.rb +4 -0
  106. data/spec/models/student.rb +3 -0
  107. data/spec/models/submission.rb +4 -0
  108. data/spec/models/teacher.rb +3 -0
  109. data/spec/models/user.rb +4 -0
  110. data/spec/models/writer.rb +2 -0
  111. data/spec/spec_helper.rb +103 -0
  112. data/spec/support/bullet_ext.rb +55 -0
  113. data/spec/support/mongo_seed.rb +65 -0
  114. data/spec/support/rack_double.rb +55 -0
  115. data/spec/support/sqlite_seed.rb +229 -0
  116. data/tasks/bullet_tasks.rake +9 -0
  117. data/test.sh +15 -0
  118. metadata +246 -0
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 - 2010 Richard Huang (flyerhzm@gmail.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,428 @@
1
+ # Bullet
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/bullet.png)](http://badge.fury.io/rb/bullet)
4
+ [![Build Status](https://secure.travis-ci.org/flyerhzm/bullet.png)](http://travis-ci.org/flyerhzm/bullet)
5
+ [![Coverage Status](https://coveralls.io/repos/flyerhzm/bullet/badge.png?branch=master)](https://coveralls.io/r/flyerhzm/bullet)
6
+ <a href="https://codeclimate.com/github/flyerhzm/bullet"><img src="https://codeclimate.com/github/flyerhzm/bullet.png" /></a>
7
+ [![Coderwall Endorse](http://api.coderwall.com/flyerhzm/endorsecount.png)](http://coderwall.com/flyerhzm)
8
+
9
+ The Bullet gem is designed to help you increase your application's performance by reducing the number of queries it makes. It will watch your queries while you develop your application and notify you when you should add eager loading (N+1 queries), when you're using eager loading that isn't necessary and when you should use counter cache.
10
+
11
+ Best practice is to use Bullet in development mode or custom mode (staging, profile, etc.). The last thing you want is your clients getting alerts about how lazy you are.
12
+
13
+ Bullet gem now supports **activerecord** >= 3.0 and **mongoid** >= 2.4.1.
14
+
15
+ If you use activercord 2.x, please use bullet <= 4.5.0
16
+
17
+ ## External Introduction
18
+
19
+ * [http://railscasts.com/episodes/372-bullet](http://railscasts.com/episodes/372-bullet)
20
+ * [http://ruby5.envylabs.com/episodes/9-episode-8-september-8-2009](http://ruby5.envylabs.com/episodes/9-episode-8-september-8-2009)
21
+ * [http://railslab.newrelic.com/2009/10/23/episode-19-on-the-edge-part-1](http://railslab.newrelic.com/2009/10/23/episode-19-on-the-edge-part-1)
22
+ * [http://weblog.rubyonrails.org/2009/10/22/community-highlights](http://weblog.rubyonrails.org/2009/10/22/community-highlights)
23
+
24
+ ## Install
25
+
26
+ You can install it as a gem:
27
+
28
+ ```
29
+ gem install bullet
30
+ ```
31
+
32
+ or add it into a Gemfile (Bundler):
33
+
34
+
35
+ ```ruby
36
+ gem "bullet", :group => "development"
37
+ ```
38
+
39
+ ## Configuration
40
+
41
+ Bullet won't do ANYTHING unless you tell it to explicitly. Append to
42
+ `config/environments/development.rb` initializer with the following code:
43
+
44
+ ```ruby
45
+ config.after_initialize do
46
+ Bullet.enable = true
47
+ Bullet.alert = true
48
+ Bullet.bullet_logger = true
49
+ Bullet.console = true
50
+ Bullet.growl = true
51
+ Bullet.xmpp = { :account => 'bullets_account@jabber.org',
52
+ :password => 'bullets_password_for_jabber',
53
+ :receiver => 'your_account@jabber.org',
54
+ :show_online_status => true }
55
+ Bullet.rails_logger = true
56
+ Bullet.bugsnag = true
57
+ Bullet.airbrake = true
58
+ Bullet.add_footer = true
59
+ Bullet.stacktrace_includes = [ 'your_gem', 'your_middleware' ]
60
+ end
61
+ ```
62
+
63
+ The notifier of bullet is a wrap of [uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
64
+
65
+ The code above will enable all seven of the Bullet notification systems:
66
+ * `Bullet.enable`: enable Bullet gem, otherwise do nothing
67
+ * `Bullet.alert`: pop up a JavaScript alert in the browser
68
+ * `Bullet.bullet_logger`: log to the Bullet log file (Rails.root/log/bullet.log)
69
+ * `Bullet.rails_logger`: add warnings directly to the Rails log
70
+ * `Bullet.airbrake`: add notifications to airbrake
71
+ * `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
72
+ * `Bullet.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
73
+ * `Bullet.xmpp`: send XMPP/Jabber notifications to the receiver indicated. Note that the code will currently not handle the adding of contacts, so you will need to make both accounts indicated know each other manually before you will receive any notifications. If you restart the development server frequently, the 'coming online' sound for the bullet account may start to annoy - in this case set :show_online_status to false; you will still get notifications, but the bullet account won't announce it's online status anymore.
74
+ * `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
75
+ * `Bullet.add_footer`: adds the details in the bottom left corner of the page
76
+ * `Bullet.stacktrace_includes`: include paths with any of these substrings in the stack trace, even if they are not in your main app
77
+
78
+ Bullet also allows you to disable n_plus_one_query, unused_eager_loading
79
+ and counter_cache detectors respectively.
80
+
81
+ ```ruby
82
+ Bullet.n_plus_one_query_enable = false
83
+ Bullet.unused_eager_loading_enable = false
84
+ Bullet.counter_cache_enable = false
85
+ ```
86
+
87
+ ## Whitelist
88
+
89
+ Sometimes bullet may notify n plus one query, unused eager loading or
90
+ counter cache you don't care about or they occur in the third party gems
91
+ that you can't fix, you can add whitelist to bullet
92
+
93
+ ```ruby
94
+ Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments
95
+ Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments
96
+ Bullet.add_whitelist :type => :counter_cache, :class_name => "Country", :association => :cities
97
+ ```
98
+
99
+ ## Log
100
+
101
+ The Bullet log `log/bullet.log` will look something like this:
102
+
103
+ * N+1 Query:
104
+
105
+ ```
106
+ 2009-08-25 20:40:17[INFO] N+1 Query: PATH_INFO: /posts; model: Post => associations: [comments]·
107
+ Add to your finder: :include => [:comments]
108
+ 2009-08-25 20:40:17[INFO] N+1 Query: method call stack:·
109
+ /Users/richard/Downloads/test/app/views/posts/index.html.erb:11:in `_run_erb_app47views47posts47index46html46erb'
110
+ /Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `each'
111
+ /Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `_run_erb_app47views47posts47index46html46erb'
112
+ /Users/richard/Downloads/test/app/controllers/posts_controller.rb:7:in `index'
113
+ ```
114
+
115
+ The first two lines are notifications that N+1 queries have been encountered. The remaining lines are stack traces so you can find exactly where the queries were invoked in your code, and fix them.
116
+
117
+ * Unused eager loading:
118
+
119
+ ```
120
+ 2009-08-25 20:53:56[INFO] Unused eager loadings: PATH_INFO: /posts; model: Post => associations: [comments]·
121
+ Remove from your finder: :include => [:comments]
122
+ ```
123
+
124
+ These two lines are notifications that unused eager loadings have been encountered.
125
+
126
+ * Need counter cache:
127
+
128
+ ```
129
+ 2009-09-11 09:46:50[INFO] Need Counter Cache
130
+ Post => [:comments]
131
+ ```
132
+
133
+ ## Growl, XMPP/Jabber and Airbrake Support
134
+
135
+ see [https://github.com/flyerhzm/uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
136
+
137
+ ## Important
138
+
139
+ If you find bullet does not work for you, *please disable your browser's cache*.
140
+
141
+ ## Advanced
142
+
143
+ ### Profile a job
144
+
145
+ The bullet gem uses rack middleware to profile requests. If you want to use bullet without an http server, like to profile a job, you can use use profile method and fetch warnings
146
+
147
+ ```ruby
148
+ Bullet.profile do
149
+ # do anything
150
+ end
151
+ warnings = Bullet.warnings
152
+ ```
153
+
154
+ ### Work with sinatra
155
+
156
+ Configure and use bullet rack
157
+
158
+ ```ruby
159
+ configure :development do
160
+ Bullet.enable = true
161
+ Bullet.bullet_logger = true
162
+ use Bullet::Rack
163
+ end
164
+ ```
165
+
166
+ ### Run in tests
167
+
168
+ First you need to enable bullet in test environment.
169
+
170
+ ```ruby
171
+ # config/environments/test.rb
172
+ config.after_initialize do
173
+ Bullet.enable = true
174
+ Bullet.bullet_logger = true
175
+ Bullet.raise = true # raise an error if n+1 query occurs
176
+ end
177
+ ```
178
+
179
+ Then wrap each test in bullet api.
180
+
181
+ ```ruby
182
+ # spec/spec_helper.rb
183
+ if Bullet.enable?
184
+ config.before(:each) do
185
+ Bullet.start_request
186
+ end
187
+
188
+ config.after(:each) do
189
+ Bullet.perform_out_of_channel_notifications if Bullet.notification?
190
+ Bullet.end_request
191
+ end
192
+ end
193
+ ```
194
+
195
+ ## Debug Mode
196
+
197
+ Bullet outputs some details info, to enable debug mode, set DEBUG=true
198
+ env.
199
+
200
+ ## Contributors
201
+
202
+ [https://github.com/flyerhzm/bullet/contributors](https://github.com/flyerhzm/bullet/contributors)
203
+
204
+ ## Step by step example
205
+
206
+ Bullet is designed to function as you browse through your application in development. It will alert you whenever it encounters N+1 queries or unused eager loading.
207
+
208
+ 1\. setup test environment
209
+
210
+ ```
211
+ $ rails new test_bullet
212
+ $ cd test_bullet
213
+ $ rails g scaffold post name:string
214
+ $ rails g scaffold comment name:string post_id:integer
215
+ $ bundle exec rake db:migrate
216
+ ```
217
+
218
+ 2\. change `app/model/post.rb` and `app/model/comment.rb`
219
+
220
+ ```ruby
221
+ class Post < ActiveRecord::Base
222
+ has_many :comments
223
+ end
224
+
225
+ class Comment < ActiveRecord::Base
226
+ belongs_to :post
227
+ end
228
+ ```
229
+
230
+ 3\. go to `rails c` and execute
231
+
232
+ ```ruby
233
+ post1 = Post.create(:name => 'first')
234
+ post2 = Post.create(:name => 'second')
235
+ post1.comments.create(:name => 'first')
236
+ post1.comments.create(:name => 'second')
237
+ post2.comments.create(:name => 'third')
238
+ post2.comments.create(:name => 'fourth')
239
+ ```
240
+
241
+ 4\. change the `app/views/posts/index.html.erb` to produce a N+1 query
242
+
243
+ ```
244
+ <% @posts.each do |post| %>
245
+ <tr>
246
+ <td><%= post.name %></td>
247
+ <td><%= post.comments.map(&:name) %></td>
248
+ <td><%= link_to 'Show', post %></td>
249
+ <td><%= link_to 'Edit', edit_post_path(post) %></td>
250
+ <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
251
+ </tr>
252
+ <% end %>
253
+ ```
254
+
255
+ 5\. add bullet gem to `Gemfile`
256
+
257
+ ```ruby
258
+ gem "bullet"
259
+ ```
260
+
261
+ And run
262
+
263
+ ```
264
+ bundle install
265
+ ```
266
+
267
+ 6\. enable the bullet gem in development, add a line to
268
+ `config/environments/development.rb`
269
+
270
+ ```ruby
271
+ config.after_initialize do
272
+ Bullet.enable = true
273
+ Bullet.alert = true
274
+ Bullet.bullet_logger = true
275
+ Bullet.console = true
276
+ # Bullet.growl = true
277
+ Bullet.rails_logger = true
278
+ Bullet.add_footer = true
279
+ end
280
+ ```
281
+
282
+ 7\. start server
283
+
284
+ ```
285
+ $ rails s
286
+ ```
287
+
288
+ 8\. input http://localhost:3000/posts in browser, then you will see a popup alert box says
289
+
290
+ ```
291
+ The request has unused preload associations as follows:
292
+ None
293
+ The request has N+1 queries as follows:
294
+ model: Post => associations: [comment]
295
+ ```
296
+
297
+ which means there is a N+1 query from post object to comments associations.
298
+
299
+ In the meanwhile, there's a log appended into `log/bullet.log` file
300
+
301
+ ```
302
+ 2010-03-07 14:12:18[INFO] N+1 Query in /posts
303
+ Post => [:comments]
304
+ Add to your finder: :include => [:comments]
305
+ 2010-03-07 14:12:18[INFO] N+1 Query method call stack
306
+ /home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:14:in `_render_template__600522146_80203160_0'
307
+ /home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:11:in `each'
308
+ /home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:11:in `_render_template__600522146_80203160_0'
309
+ /home/flyerhzm/Downloads/test_bullet/app/controllers/posts_controller.rb:7:in `index'
310
+ ```
311
+
312
+ The generated SQLs are
313
+
314
+ ```
315
+ Post Load (1.0ms) SELECT * FROM "posts"
316
+ Comment Load (0.4ms) SELECT * FROM "comments" WHERE ("comments".post_id = 1)
317
+ Comment Load (0.3ms) SELECT * FROM "comments" WHERE ("comments".post_id = 2)
318
+ ```
319
+
320
+
321
+ 9\. fix the N+1 query, change `app/controllers/posts_controller.rb` file
322
+
323
+ ```ruby
324
+ def index
325
+ @posts = Post.includes(:comments)
326
+
327
+ respond_to do |format|
328
+ format.html # index.html.erb
329
+ format.xml { render :xml => @posts }
330
+ end
331
+ end
332
+ ```
333
+
334
+ 10\. refresh http://localhost:3000/posts page, no alert box and no log appended.
335
+
336
+ The generated SQLs are
337
+
338
+ ```
339
+ Post Load (0.5ms) SELECT * FROM "posts"
340
+ Comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE ("comments".post_id IN (1,2))
341
+ ```
342
+
343
+ a N+1 query fixed. Cool!
344
+
345
+ 11\. now simulate unused eager loading. Change
346
+ `app/controllers/posts_controller.rb` and
347
+ `app/views/posts/index.html.erb`
348
+
349
+ ```ruby
350
+ def index
351
+ @posts = Post.includes(:comments)
352
+
353
+ respond_to do |format|
354
+ format.html # index.html.erb
355
+ format.xml { render :xml => @posts }
356
+ end
357
+ end
358
+ ```
359
+
360
+ ```
361
+ <% @posts.each do |post| %>
362
+ <tr>
363
+ <td><%= post.name %></td>
364
+ <td><%= link_to 'Show', post %></td>
365
+ <td><%= link_to 'Edit', edit_post_path(post) %></td>
366
+ <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
367
+ </tr>
368
+ <% end %>
369
+ ```
370
+
371
+ 12\. refresh http://localhost:3000/posts page, then you will see a popup alert box says
372
+
373
+ ```
374
+ The request has unused preload associations as follows:
375
+ model: Post => associations: [comment]
376
+ The request has N+1 queries as follows:
377
+ None
378
+ ```
379
+
380
+ In the meanwhile, there's a log appended into `log/bullet.log` file
381
+
382
+ ```
383
+ 2009-08-25 21:13:22[INFO] Unused preload associations: PATH_INFO: /posts; model: Post => associations: [comments]·
384
+ Remove from your finder: :include => [:comments]
385
+ ```
386
+
387
+ 13\. simulate counter_cache. Change `app/controllers/posts_controller.rb`
388
+ and `app/views/posts/index.html.erb`
389
+
390
+ ```ruby
391
+ def index
392
+ @posts = Post.all
393
+
394
+ respond_to do |format|
395
+ format.html # index.html.erb
396
+ format.xml { render :xml => @posts }
397
+ end
398
+ end
399
+ ```
400
+
401
+ ```
402
+ <% @posts.each do |post| %>
403
+ <tr>
404
+ <td><%= post.name %></td>
405
+ <td><%= post.comments.size %></td>
406
+ <td><%= link_to 'Show', post %></td>
407
+ <td><%= link_to 'Edit', edit_post_path(post) %></td>
408
+ <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
409
+ </tr>
410
+ <% end %>
411
+ ```
412
+
413
+ 14\. refresh http://localhost:3000/posts page, then you will see a popup alert box says
414
+
415
+ ```
416
+ Need counter cache
417
+ Post => [:comments]
418
+ ```
419
+
420
+ In the meanwhile, there's a log appended into `log/bullet.log` file.
421
+
422
+ ```
423
+ 2009-09-11 10:07:10[INFO] Need Counter Cache
424
+ Post => [:comments]
425
+ ```
426
+
427
+
428
+ Copyright (c) 2009 - 2014 Richard Huang (flyerhzm@gmail.com), released under the MIT license
@@ -0,0 +1,52 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+ require "bundler"
3
+ Bundler.setup
4
+
5
+ require "rake"
6
+ require "rspec"
7
+ require "rspec/core/rake_task"
8
+
9
+ require "bullet/version"
10
+
11
+ task :build do
12
+ system "gem build bullet_instructure.gemspec"
13
+ end
14
+
15
+ task :install => :build do
16
+ system "sudo gem install bullet_instructure-#{Bullet::VERSION}.gem"
17
+ end
18
+
19
+ task :release => :build do
20
+ puts "Tagging #{Bullet::VERSION}..."
21
+ system "git tag -a #{Bullet::VERSION} -m 'Tagging #{Bullet::VERSION}'"
22
+ puts "Pushing to Github..."
23
+ system "git push --tags"
24
+ puts "Pushing to rubygems.org..."
25
+ system "gem push bullet-#{Bullet::VERSION}.gem"
26
+ end
27
+
28
+ RSpec::Core::RakeTask.new(:spec) do |spec|
29
+ spec.pattern = "spec/**/*_spec.rb"
30
+ end
31
+
32
+ RSpec::Core::RakeTask.new('spec:progress') do |spec|
33
+ spec.rspec_opts = %w(--format progress)
34
+ spec.pattern = "spec/**/*_spec.rb"
35
+ end
36
+
37
+
38
+ begin
39
+ require 'rdoc/task'
40
+
41
+ desc "Generate documentation for the plugin."
42
+ Rake::RDocTask.new do |rdoc|
43
+ rdoc.rdoc_dir = "rdoc"
44
+ rdoc.title = "bullet_instructure #{Bullet::VERSION}"
45
+ rdoc.rdoc_files.include("README*")
46
+ rdoc.rdoc_files.include("lib/**/*.rb")
47
+ end
48
+ rescue LoadError
49
+ puts 'RDocTask is not supported for this platform'
50
+ end
51
+
52
+ task :default => :spec