brakefast 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8eb0828ea86e50b2c475a7d88359d907e350bc20
4
+ data.tar.gz: 40e8588718b3babe9075ae23d86deae3128090c0
5
+ SHA512:
6
+ metadata.gz: c109fa8a8021c1f9b06d952f6edf71a9b860de7f4ed7c965050ae6fa3870f87908f99a72aac1852bd0540149ebcb55986b590faf59fded74ff2c8c51f37126a4
7
+ data.tar.gz: 0a193a1b9474c0a524030fbcbfcdcbfc1a8e76f684ff39ee155fbec1044ca95815d3ccbcb71ac3922898bfabcd6a5e5483156db04b8e79e9237c79e380a4c2c4
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ log/**
2
+ pkg/**
3
+ .DS_Store
4
+ lib/.DS_Store
5
+ .*.swp
6
+ coverage.data
7
+ tags
8
+ .bundle
9
+ *.gem
10
+ benchmark_profile*
11
+ /nbproject/private/
12
+ coverage/
13
+ .coveralls.yml
14
+ Gemfile*.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,48 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.0
5
+ - 2.1
6
+ - 2.2
7
+ gemfile:
8
+ - Gemfile.rails-4.2
9
+ - Gemfile.rails-4.1
10
+ - Gemfile.rails-4.0
11
+ - Gemfile.rails-3.2
12
+ - Gemfile.rails-3.1
13
+ - Gemfile.rails-3.0
14
+ - Gemfile.mongoid-5.0
15
+ - Gemfile.mongoid-4.0
16
+ - Gemfile.mongoid-3.1
17
+ - Gemfile.mongoid-3.0
18
+ - Gemfile.mongoid-2.8
19
+ - Gemfile.mongoid-2.7
20
+ - Gemfile.mongoid-2.6
21
+ - Gemfile.mongoid-2.5
22
+ - Gemfile.mongoid-2.4
23
+ env:
24
+ - DB=sqlite
25
+ services:
26
+ - mongodb
27
+ matrix:
28
+ exclude:
29
+ - rvm: 2.2
30
+ gemfile: Gemfile.rails-3.0
31
+ - rvm: 2.2
32
+ gemfile: Gemfile.rails-3.1
33
+ - rvm: 2.2
34
+ gemfile: Gemfile.rails-3.2
35
+ - rvm: 2.2
36
+ gemfile: Gemfile.mongoid-3.1
37
+ - rvm: 2.2
38
+ gemfile: Gemfile.mongoid-3.0
39
+ - rvm: 2.2
40
+ gemfile: Gemfile.mongoid-2.8
41
+ - rvm: 2.2
42
+ gemfile: Gemfile.mongoid-2.7
43
+ - rvm: 2.2
44
+ gemfile: Gemfile.mongoid-2.6
45
+ - rvm: 2.2
46
+ gemfile: Gemfile.mongoid-2.5
47
+ - rvm: 2.2
48
+ gemfile: Gemfile.mongoid-2.4
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Next Release
2
+
3
+ ## 0.0.1 (08/30/2015)
4
+
5
+ * First release
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ =begin
6
+ gem 'rails', github: 'rails/rails'
7
+ gem 'sqlite3', platforms: [:ruby]
8
+ gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
9
+ gem 'activerecord-import'
10
+ =end
11
+
12
+ gem 'rspec'
13
+ gem 'guard'
14
+ gem 'guard-rspec'
15
+
16
+ gem 'coveralls', require: false
17
+
18
+ platforms :rbx do
19
+ gem 'rubysl', '~> 2.0'
20
+ gem 'rubinius-developer_tools'
21
+ end
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2, :all_after_pass => false, :all_on_start => false, :cli => "--color --format nested --fail-fast" do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
data/Hacking.md ADDED
@@ -0,0 +1,74 @@
1
+ # Bullet Overview for Developers
2
+
3
+ This file aims to give developers a quick tour of the bullet internals, making
4
+ it (hopefully) easier to extend or enhance the Bullet gem.
5
+
6
+ ## General Control Flow aka. 10000 Meter View
7
+
8
+ When Rails is initialized, Bullet will extend ActiveRecord (and if you're using
9
+ Rails 2.x ActiveController too) with the relevant modules and methods found
10
+ in lib/bullet/active_recordX.rb and lib/bullet/action_controller2.rb. If you're
11
+ running Rails 3, Bullet will integrate itself as a middleware into the Rack
12
+ stack, so ActionController does not need to be extended.
13
+
14
+ The ActiveRecord extensions will call methods in a given detector class, when
15
+ certain methods are called.
16
+
17
+ Detector classes contain all the logic to recognize
18
+ a noteworthy event. If such an event is detected, an instance of the
19
+ corresponding Notification class is created and stored in a Set instance in the
20
+ main Bullet module (the 'notification collector').
21
+
22
+ Notification instances contain the message that will be displayed, and will
23
+ use a Presenter class to display their message to the user.
24
+
25
+ So the flow of a request goes like this:
26
+ 1. Bullet.start_request is called, which resets all the detectors and empties
27
+ the notification collector
28
+ 2. The request is handled by Rails, and the installed ActiveRecord extensions
29
+ trigger Detector callbacks
30
+ 3. Detectors once called, will determine whether something noteworthy happend.
31
+ If yes, then a Notification is created and stored in the notification collector.
32
+ 4. Rails finishes handling the request
33
+ 5. For each notification in the collector, Bullet will iterate over each
34
+ Presenter and will try to generate an inline message that will be appended to
35
+ the generated response body.
36
+ 6. The response is returned to the client.
37
+ 7. Bullet will try to generate an out-of-channel message for each notification.
38
+ 8. Bullet calls end_request for each detector.
39
+ 9. Goto 1.
40
+
41
+ ## Adding Notification Types
42
+
43
+ If you want to add more kinds of things that Bullet can detect, a little more
44
+ work is needed than if you were just adding a Presenter, but the concepts are
45
+ similar.
46
+
47
+ * Add the class to the DETECTORS constant in the main Bullet module
48
+ * Add (if needed) Rails monkey patches to Bullet.enable
49
+ * Add an autoload directive to lib/bullet/detector.rb
50
+ * Create a corresponding notification class in the Bullet::Notification namespace
51
+ * Add an autoload directive to lib/bullet/notification.rb
52
+
53
+ As a rule of thumb, you can assume that each Detector will have its own
54
+ Notification class. If you follow the principle of Separation of Concerns I
55
+ can't really think of an example where one would deviate from this rule.
56
+
57
+ Since the detection of pathological associations is a bit hairy, I'd recommend
58
+ having a look at the counter cache detector and associated notification to get
59
+ a feel for what is needed to get off the ground.
60
+
61
+ ### Detectors
62
+
63
+ The only things you'll need to consider when building your Detector class is
64
+ that it will need to supply the .start_request, .end_request and .clear class
65
+ methods.
66
+
67
+ Simple implementations are provided by Bullet::Detector::Base for start_request
68
+ and end_request, you will have to supply your own clear method.
69
+
70
+ ### Notifications
71
+
72
+ For notifications you will want to supply a #title and #body instance method,
73
+ and check to see if the #initialize and #full_notice methods in the
74
+ Bullet::Notification::Base class fit your needs.
data/MIT-LICENSE ADDED
@@ -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.
data/README.md ADDED
@@ -0,0 +1,451 @@
1
+ # Brakefast
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/brakefast.png)](http://badge.fury.io/rb/brakefast)
4
+ [![Build Status](https://secure.travis-ci.org/flyerhzm/brakefast.png)](http://travis-ci.org/flyerhzm/brakefast)
5
+ [![Coverage Status](https://coveralls.io/repos/flyerhzm/brakefast/badge.png?branch=master)](https://coveralls.io/r/flyerhzm/brakefast)
6
+ <a href="https://codeclimate.com/github/flyerhzm/brakefast"><img src="https://codeclimate.com/github/flyerhzm/brakefast.png" /></a>
7
+ [![Coderwall Endorse](http://api.coderwall.com/flyerhzm/endorsecount.png)](http://coderwall.com/flyerhzm)
8
+
9
+ The Brakefast gem is designed to help you reduce your application's vulnerability. It will watch your code with using [brakeman](http://brakemanscanner.org) while you develop your application and notify you when you use vulnerable code.
10
+
11
+ Best practice is to use Brakefast 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
+ ## Install
14
+
15
+ You can install it as a gem:
16
+
17
+ ```
18
+ gem install brakefast
19
+ ```
20
+
21
+ or add it into a Gemfile (Bundler):
22
+
23
+
24
+ ```ruby
25
+ gem "brakefast", :group => "development"
26
+ ```
27
+
28
+ ## Configuration
29
+
30
+ Brakefast won't do ANYTHING unless you tell it to explicitly. Append to
31
+ `config/environments/development.rb` initializer with the following code:
32
+
33
+ ```ruby
34
+ config.after_initialize do
35
+ Brakefast.enable = true
36
+ Brakefast.alert = true
37
+ Brakefast.brakefast_logger = true
38
+ Brakefast.console = true
39
+ Brakefast.growl = true
40
+ Brakefast.xmpp = { :account => 'brakefasts_account@jabber.org',
41
+ :password => 'brakefasts_password_for_jabber',
42
+ :receiver => 'your_account@jabber.org',
43
+ :show_online_status => true }
44
+ Brakefast.rails_logger = true
45
+ Brakefast.honeybadger = true
46
+ Brakefast.bugsnag = true
47
+ Brakefast.airbrake = true
48
+ Brakefast.rollbar = true
49
+ Brakefast.add_footer = true
50
+ Brakefast.stacktrace_includes = [ 'your_gem', 'your_middleware' ]
51
+ Brakefast.slack = { webhook_url: 'http://some.slack.url', foo: 'bar' }
52
+ end
53
+ ```
54
+
55
+ The notifier of Brakefast is a wrap of [uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
56
+
57
+ The code above will enable all seven of the Brakefast notification systems:
58
+ * `Brakefast.enable`: enable Brakefast gem, otherwise do nothing
59
+ * `Brakefast.alert`: pop up a JavaScript alert in the browser
60
+ * `Brakefast.brakefast_logger`: log to the Brakefast log file (Rails.root/log/brakefast.log)
61
+ * `Brakefast.rails_logger`: add warnings directly to the Rails log
62
+ * `Brakefast.honeybadger`: add notifications to Honeybadger
63
+ * `Brakefast.bugsnag`: add notifications to bugsnag
64
+ * `Brakefast.airbrake`: add notifications to airbrake
65
+ * `Brakefast.rollbar`: add notifications to rollbar
66
+ * `Brakefast.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
67
+ * `Brakefast.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
68
+ * `Brakefast.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 Brakefast account may start to annoy - in this case set :show_online_status to false; you will still get notifications, but the Brakefast account won't announce it's online status anymore.
69
+ * `Brakefast.raise`: raise errors, useful for making your specs fail unless they have optimized queries
70
+ * `Brakefast.add_footer`: adds the details in the bottom left corner of the page
71
+ * `Brakefast.stacktrace_includes`: include paths with any of these substrings in the stack trace, even if they are not in your main app
72
+ * `Brakefast.slack`: add notifications to slack
73
+
74
+ Brakefast also allows you to disable any of its detectors.
75
+
76
+ ```ruby
77
+ # Each of these settings defaults to true
78
+
79
+ # Detect errors
80
+ Brakefast.errors = false
81
+
82
+ # Detect controller warnings
83
+ Brakefast.controller_warnings = false
84
+
85
+ # Detect generic warnings
86
+ Brakefast.generic_warnings = false
87
+
88
+ # Detect model warnings
89
+ Brakefast.model_warnings = false
90
+ ```
91
+
92
+ TODO: update below
93
+
94
+ ## Whitelist
95
+
96
+ Sometimes Brakefast may notify you of query problems you don't care to fix, or
97
+ which come from outside your code. You can whitelist these to ignore them:
98
+
99
+ ```ruby
100
+ Brakefast.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments
101
+ Brakefast.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments
102
+ Brakefast.add_whitelist :type => :counter_cache, :class_name => "Country", :association => :cities
103
+ ```
104
+
105
+ If you want to skip brakefast in some specific controller actions, you can
106
+ do like
107
+
108
+ ```ruby
109
+ class ApplicationController < ActionController::Base
110
+ around_action :skip_brakefast
111
+
112
+ def skip_brakefast
113
+ Brakefast.enable = false
114
+ yield
115
+ ensure
116
+ Brakefast.enable = true
117
+ end
118
+ end
119
+ ```
120
+
121
+ ## Log
122
+
123
+ The Brakefast log `log/brakefast.log` will look something like this:
124
+
125
+ * N+1 Query:
126
+
127
+ ```
128
+ 2009-08-25 20:40:17[INFO] N+1 Query: PATH_INFO: /posts; model: Post => associations: [comments]·
129
+ Add to your finder: :include => [:comments]
130
+ 2009-08-25 20:40:17[INFO] N+1 Query: method call stack:·
131
+ /Users/richard/Downloads/test/app/views/posts/index.html.erb:11:in `_run_erb_app47views47posts47index46html46erb'
132
+ /Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `each'
133
+ /Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `_run_erb_app47views47posts47index46html46erb'
134
+ /Users/richard/Downloads/test/app/controllers/posts_controller.rb:7:in `index'
135
+ ```
136
+
137
+ 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.
138
+
139
+ * Unused eager loading:
140
+
141
+ ```
142
+ 2009-08-25 20:53:56[INFO] Unused eager loadings: PATH_INFO: /posts; model: Post => associations: [comments]·
143
+ Remove from your finder: :include => [:comments]
144
+ ```
145
+
146
+ These two lines are notifications that unused eager loadings have been encountered.
147
+
148
+ * Need counter cache:
149
+
150
+ ```
151
+ 2009-09-11 09:46:50[INFO] Need Counter Cache
152
+ Post => [:comments]
153
+ ```
154
+
155
+ ## Growl, XMPP/Jabber and Airbrake Support
156
+
157
+ see [https://github.com/flyerhzm/uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
158
+
159
+ ## Important
160
+
161
+ If you find Brakefast does not work for you, *please disable your browser's cache*.
162
+
163
+ ## Advanced
164
+
165
+ ### Profile a job
166
+
167
+ The Brakefast gem uses rack middleware to profile requests. If you want to use Brakefast without an http server, like to profile a job, you can use use profile method and fetch warnings
168
+
169
+ ```ruby
170
+ Brakefast.profile do
171
+ # do anything
172
+
173
+ warnings = Brakefast.warnings
174
+ end
175
+ ```
176
+
177
+ ### Work with sinatra
178
+
179
+ Configure and use `Brakefast::Rack`
180
+
181
+ ```ruby
182
+ configure :development do
183
+ Brakefast.enable = true
184
+ Brakefast.brakefast_logger = true
185
+ use Brakefast::Rack
186
+ end
187
+ ```
188
+
189
+ ### Run in tests
190
+
191
+ First you need to enable Brakefast in test environment.
192
+
193
+ ```ruby
194
+ # config/environments/test.rb
195
+ config.after_initialize do
196
+ Brakefast.enable = true
197
+ Brakefast.brakefast_logger = true
198
+ Brakefast.raise = true # raise an error if n+1 query occurs
199
+ end
200
+ ```
201
+
202
+ Then wrap each test in Brakefast api.
203
+
204
+ ```ruby
205
+ # spec/spec_helper.rb
206
+ if Brakefast.enable?
207
+ config.before(:each) do
208
+ Brakefast.start_request
209
+ end
210
+
211
+ config.after(:each) do
212
+ Brakefast.perform_out_of_channel_notifications if Brakefast.notification?
213
+ Brakefast.end_request
214
+ end
215
+ end
216
+ ```
217
+
218
+ ## Debug Mode
219
+
220
+ Brakefast outputs some details info, to enable debug mode, set
221
+ `BRAKEFAST_DEBUG=true` env.
222
+
223
+ ## Contributors
224
+
225
+ [https://github.com/flyerhzm/brakefast/contributors](https://github.com/flyerhzm/brakefast/contributors)
226
+
227
+ ## Demo
228
+
229
+ Brakefast is designed to function as you browse through your application in development. To see it in action, follow these steps to create, detect, and fix example query problems.
230
+
231
+ 1\. Create an example application
232
+
233
+ ```
234
+ $ rails new test_brakefast
235
+ $ cd test_brakefast
236
+ $ rails g scaffold post name:string
237
+ $ rails g scaffold comment name:string post_id:integer
238
+ $ bundle exec rake db:migrate
239
+ ```
240
+
241
+ 2\. Change `app/model/post.rb` and `app/model/comment.rb`
242
+
243
+ ```ruby
244
+ class Post < ActiveRecord::Base
245
+ has_many :comments
246
+ end
247
+
248
+ class Comment < ActiveRecord::Base
249
+ belongs_to :post
250
+ end
251
+ ```
252
+
253
+ 3\. Go to `rails c` and execute
254
+
255
+ ```ruby
256
+ post1 = Post.create(:name => 'first')
257
+ post2 = Post.create(:name => 'second')
258
+ post1.comments.create(:name => 'first')
259
+ post1.comments.create(:name => 'second')
260
+ post2.comments.create(:name => 'third')
261
+ post2.comments.create(:name => 'fourth')
262
+ ```
263
+
264
+ 4\. Change the `app/views/posts/index.html.erb` to produce a N+1 query
265
+
266
+ ```
267
+ <% @posts.each do |post| %>
268
+ <tr>
269
+ <td><%= post.name %></td>
270
+ <td><%= post.comments.map(&:name) %></td>
271
+ <td><%= link_to 'Show', post %></td>
272
+ <td><%= link_to 'Edit', edit_post_path(post) %></td>
273
+ <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
274
+ </tr>
275
+ <% end %>
276
+ ```
277
+
278
+ 5\. Add the `brakefast` gem to the `Gemfile`
279
+
280
+ ```ruby
281
+ gem "brakefast"
282
+ ```
283
+
284
+ And run
285
+
286
+ ```
287
+ bundle install
288
+ ```
289
+
290
+ 6\. enable the Brakefast gem in development, add a line to
291
+ `config/environments/development.rb`
292
+
293
+ ```ruby
294
+ config.after_initialize do
295
+ Brakefast.enable = true
296
+ Brakefast.alert = true
297
+ Brakefast.brakefast_logger = true
298
+ Brakefast.console = true
299
+ # Brakefast.growl = true
300
+ Brakefast.rails_logger = true
301
+ Brakefast.add_footer = true
302
+ end
303
+ ```
304
+
305
+ 7\. Start the server
306
+
307
+ ```
308
+ $ rails s
309
+ ```
310
+
311
+ 8\. Visit `http://localhost:3000/posts` in browser, and you will see a popup alert box that says
312
+
313
+ ```
314
+ The request has unused preload associations as follows:
315
+ None
316
+ The request has N+1 queries as follows:
317
+ model: Post => associations: [comment]
318
+ ```
319
+
320
+ which means there is a N+1 query from the Post object to its Comment association.
321
+
322
+ In the meanwhile, there's a log appended into `log/brakefast.log` file
323
+
324
+ ```
325
+ 2010-03-07 14:12:18[INFO] N+1 Query in /posts
326
+ Post => [:comments]
327
+ Add to your finder: :include => [:comments]
328
+ 2010-03-07 14:12:18[INFO] N+1 Query method call stack
329
+ /home/flyerhzm/Downloads/test_brakefast/app/views/posts/index.html.erb:14:in `_render_template__600522146_80203160_0'
330
+ /home/flyerhzm/Downloads/test_brakefast/app/views/posts/index.html.erb:11:in `each'
331
+ /home/flyerhzm/Downloads/test_brakefast/app/views/posts/index.html.erb:11:in `_render_template__600522146_80203160_0'
332
+ /home/flyerhzm/Downloads/test_brakefast/app/controllers/posts_controller.rb:7:in `index'
333
+ ```
334
+
335
+ The generated SQL is:
336
+
337
+ ```
338
+ Post Load (1.0ms) SELECT * FROM "posts"
339
+ Comment Load (0.4ms) SELECT * FROM "comments" WHERE ("comments".post_id = 1)
340
+ Comment Load (0.3ms) SELECT * FROM "comments" WHERE ("comments".post_id = 2)
341
+ ```
342
+
343
+ 9\. To fix the N+1 query, change `app/controllers/posts_controller.rb` file
344
+
345
+ ```ruby
346
+ def index
347
+ @posts = Post.includes(:comments)
348
+
349
+ respond_to do |format|
350
+ format.html # index.html.erb
351
+ format.xml { render :xml => @posts }
352
+ end
353
+ end
354
+ ```
355
+
356
+ 10\. Refresh `http://localhost:3000/posts`. Now there's no alert box and nothing new in the log.
357
+
358
+ The generated SQL is:
359
+
360
+ ```
361
+ Post Load (0.5ms) SELECT * FROM "posts"
362
+ Comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE ("comments".post_id IN (1,2))
363
+ ```
364
+
365
+ N+1 query fixed. Cool!
366
+
367
+ 11\. Now simulate unused eager loading. Change
368
+ `app/controllers/posts_controller.rb` and
369
+ `app/views/posts/index.html.erb`
370
+
371
+ ```ruby
372
+ def index
373
+ @posts = Post.includes(:comments)
374
+
375
+ respond_to do |format|
376
+ format.html # index.html.erb
377
+ format.xml { render :xml => @posts }
378
+ end
379
+ end
380
+ ```
381
+
382
+ ```
383
+ <% @posts.each do |post| %>
384
+ <tr>
385
+ <td><%= post.name %></td>
386
+ <td><%= link_to 'Show', post %></td>
387
+ <td><%= link_to 'Edit', edit_post_path(post) %></td>
388
+ <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
389
+ </tr>
390
+ <% end %>
391
+ ```
392
+
393
+ 12\. Refresh `http://localhost:3000/posts`, and you will see a popup alert box that says
394
+
395
+ ```
396
+ The request has unused preload associations as follows:
397
+ model: Post => associations: [comment]
398
+ The request has N+1 queries as follows:
399
+ None
400
+ ```
401
+
402
+ Meanwhile, there's a line appended to `log/brakefast.log`
403
+
404
+ ```
405
+ 2009-08-25 21:13:22[INFO] Unused preload associations: PATH_INFO: /posts; model: Post => associations: [comments]·
406
+ Remove from your finder: :include => [:comments]
407
+ ```
408
+
409
+ 13\. Simulate counter_cache. Change `app/controllers/posts_controller.rb`
410
+ and `app/views/posts/index.html.erb`
411
+
412
+ ```ruby
413
+ def index
414
+ @posts = Post.all
415
+
416
+ respond_to do |format|
417
+ format.html # index.html.erb
418
+ format.xml { render :xml => @posts }
419
+ end
420
+ end
421
+ ```
422
+
423
+ ```
424
+ <% @posts.each do |post| %>
425
+ <tr>
426
+ <td><%= post.name %></td>
427
+ <td><%= post.comments.size %></td>
428
+ <td><%= link_to 'Show', post %></td>
429
+ <td><%= link_to 'Edit', edit_post_path(post) %></td>
430
+ <td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
431
+ </tr>
432
+ <% end %>
433
+ ```
434
+
435
+ 14\. Refresh `http://localhost:3000/posts`, then you will see a popup alert box that says
436
+
437
+ ```
438
+ Need counter cache
439
+ Post => [:comments]
440
+ ```
441
+
442
+ Meanwhile, there's a line appended to `log/brakefast.log`
443
+
444
+ ```
445
+ 2009-09-11 10:07:10[INFO] Need Counter Cache
446
+ Post => [:comments]
447
+ ```
448
+
449
+ Copyright (c) 2009 - 2015 Richard Huang (flyerhzm (at) gmail.com), released under the MIT license in bullet original sentences
450
+
451
+ Copyright (c) 2015 - Sho Hashimoto (sho.hsmt (at) gmail.com), released under the MIT license in brakefast sentences
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec