bullet 2.0.0.beta.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rvmrc +2 -0
- data/.rvmrc.example +2 -0
- data/.watchr +24 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +105 -0
- data/Hacking.textile +69 -0
- data/MIT-LICENSE +1 -1
- data/README.textile +61 -49
- data/README_for_rails2.textile +41 -42
- data/Rakefile +40 -29
- data/bullet.gemspec +17 -60
- data/lib/bullet/action_controller2.rb +6 -6
- data/lib/bullet/active_record2.rb +17 -16
- data/lib/bullet/active_record3.rb +17 -25
- data/lib/bullet/active_record31.rb +96 -0
- data/lib/bullet/detector/association.rb +144 -0
- data/lib/bullet/detector/base.rb +12 -0
- data/lib/bullet/detector/counter.rb +43 -0
- data/lib/bullet/detector/n_plus_one_query.rb +39 -0
- data/lib/bullet/detector/unused_eager_association.rb +41 -0
- data/lib/bullet/detector.rb +9 -0
- data/lib/bullet/notification/base.rb +61 -0
- data/lib/bullet/notification/counter_cache.rb +13 -0
- data/lib/bullet/notification/n_plus_one_query.rb +32 -0
- data/lib/bullet/notification/unused_eager_loading.rb +14 -0
- data/lib/bullet/notification.rb +4 -79
- data/lib/bullet/notification_collector.rb +25 -0
- data/lib/bullet/rack.rb +44 -0
- data/lib/bullet/registry/association.rb +15 -0
- data/lib/bullet/registry/base.rb +37 -0
- data/lib/bullet/registry/object.rb +15 -0
- data/lib/bullet/registry.rb +7 -0
- data/lib/bullet/version.rb +5 -0
- data/lib/bullet.rb +64 -43
- data/perf/benchmark.rb +106 -0
- data/spec/bullet/association_for_chris_spec.rb +6 -6
- data/spec/bullet/association_for_peschkaj_spec.rb +6 -6
- data/spec/bullet/association_spec.rb +140 -294
- data/spec/bullet/counter_spec.rb +10 -10
- data/spec/spec_helper.rb +51 -17
- metadata +72 -57
- data/VERSION +0 -1
- data/lib/bullet/association.rb +0 -294
- data/lib/bullet/counter.rb +0 -101
- data/lib/bullet/logger.rb +0 -9
- data/lib/bulletware.rb +0 -42
- data/spec/spec.opts +0 -3
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
data/.rvmrc.example
ADDED
data/.watchr
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# vim:set filetype=ruby:
|
|
2
|
+
def run(cmd)
|
|
3
|
+
puts cmd
|
|
4
|
+
system cmd
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def spec(file)
|
|
8
|
+
if File.exists?(file)
|
|
9
|
+
run("rspec #{file}")
|
|
10
|
+
else
|
|
11
|
+
puts("Spec: #{file} does not exist.")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
watch("spec/.*/*_spec\.rb") do |match|
|
|
16
|
+
puts(match[0])
|
|
17
|
+
spec(match[0])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
watch("lib/(.*/.*)\.rb") do |match|
|
|
21
|
+
puts(match[1])
|
|
22
|
+
spec("spec/#{match[1]}_spec.rb")
|
|
23
|
+
end
|
|
24
|
+
|
data/Gemfile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Use `bundle install` in order to install these gems
|
|
2
|
+
# Use `bundle exec rake` in order to run the specs using the bundle
|
|
3
|
+
source "http://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gemspec
|
|
6
|
+
|
|
7
|
+
gem 'rails'
|
|
8
|
+
gem 'sqlite3-ruby', :require => 'sqlite3'
|
|
9
|
+
gem 'mysql'
|
|
10
|
+
gem 'activerecord-import'
|
|
11
|
+
|
|
12
|
+
gem "rspec"
|
|
13
|
+
gem "watchr"
|
|
14
|
+
|
|
15
|
+
gem "perftools.rb"
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
bullet (2.1.0)
|
|
5
|
+
uniform_notifier (~> 1.0.0)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: http://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
abstract (1.0.0)
|
|
11
|
+
actionmailer (3.0.11)
|
|
12
|
+
actionpack (= 3.0.11)
|
|
13
|
+
mail (~> 2.2.19)
|
|
14
|
+
actionpack (3.0.11)
|
|
15
|
+
activemodel (= 3.0.11)
|
|
16
|
+
activesupport (= 3.0.11)
|
|
17
|
+
builder (~> 2.1.2)
|
|
18
|
+
erubis (~> 2.6.6)
|
|
19
|
+
i18n (~> 0.5.0)
|
|
20
|
+
rack (~> 1.2.1)
|
|
21
|
+
rack-mount (~> 0.6.14)
|
|
22
|
+
rack-test (~> 0.5.7)
|
|
23
|
+
tzinfo (~> 0.3.23)
|
|
24
|
+
activemodel (3.0.11)
|
|
25
|
+
activesupport (= 3.0.11)
|
|
26
|
+
builder (~> 2.1.2)
|
|
27
|
+
i18n (~> 0.5.0)
|
|
28
|
+
activerecord (3.0.11)
|
|
29
|
+
activemodel (= 3.0.11)
|
|
30
|
+
activesupport (= 3.0.11)
|
|
31
|
+
arel (~> 2.0.10)
|
|
32
|
+
tzinfo (~> 0.3.23)
|
|
33
|
+
activerecord-import (0.2.5)
|
|
34
|
+
activerecord (~> 3.0.0)
|
|
35
|
+
activeresource (3.0.11)
|
|
36
|
+
activemodel (= 3.0.11)
|
|
37
|
+
activesupport (= 3.0.11)
|
|
38
|
+
activesupport (3.0.11)
|
|
39
|
+
arel (2.0.10)
|
|
40
|
+
builder (2.1.2)
|
|
41
|
+
diff-lcs (1.1.3)
|
|
42
|
+
erubis (2.6.6)
|
|
43
|
+
abstract (>= 1.0.0)
|
|
44
|
+
i18n (0.5.0)
|
|
45
|
+
json (1.6.3)
|
|
46
|
+
mail (2.2.19)
|
|
47
|
+
activesupport (>= 2.3.6)
|
|
48
|
+
i18n (>= 0.4.0)
|
|
49
|
+
mime-types (~> 1.16)
|
|
50
|
+
treetop (~> 1.4.8)
|
|
51
|
+
mime-types (1.17.2)
|
|
52
|
+
mysql (2.8.1)
|
|
53
|
+
perftools.rb (0.5.6)
|
|
54
|
+
polyglot (0.3.3)
|
|
55
|
+
rack (1.2.4)
|
|
56
|
+
rack-mount (0.6.14)
|
|
57
|
+
rack (>= 1.0.0)
|
|
58
|
+
rack-test (0.5.7)
|
|
59
|
+
rack (>= 1.0)
|
|
60
|
+
rails (3.0.11)
|
|
61
|
+
actionmailer (= 3.0.11)
|
|
62
|
+
actionpack (= 3.0.11)
|
|
63
|
+
activerecord (= 3.0.11)
|
|
64
|
+
activeresource (= 3.0.11)
|
|
65
|
+
activesupport (= 3.0.11)
|
|
66
|
+
bundler (~> 1.0)
|
|
67
|
+
railties (= 3.0.11)
|
|
68
|
+
railties (3.0.11)
|
|
69
|
+
actionpack (= 3.0.11)
|
|
70
|
+
activesupport (= 3.0.11)
|
|
71
|
+
rake (>= 0.8.7)
|
|
72
|
+
rdoc (~> 3.4)
|
|
73
|
+
thor (~> 0.14.4)
|
|
74
|
+
rake (0.9.2.2)
|
|
75
|
+
rdoc (3.11)
|
|
76
|
+
json (~> 1.4)
|
|
77
|
+
rspec (2.7.0)
|
|
78
|
+
rspec-core (~> 2.7.0)
|
|
79
|
+
rspec-expectations (~> 2.7.0)
|
|
80
|
+
rspec-mocks (~> 2.7.0)
|
|
81
|
+
rspec-core (2.7.1)
|
|
82
|
+
rspec-expectations (2.7.0)
|
|
83
|
+
diff-lcs (~> 1.1.2)
|
|
84
|
+
rspec-mocks (2.7.0)
|
|
85
|
+
sqlite3-ruby (1.3.2)
|
|
86
|
+
thor (0.14.6)
|
|
87
|
+
treetop (1.4.10)
|
|
88
|
+
polyglot
|
|
89
|
+
polyglot (>= 0.3.1)
|
|
90
|
+
tzinfo (0.3.31)
|
|
91
|
+
uniform_notifier (1.0.1)
|
|
92
|
+
watchr (0.7)
|
|
93
|
+
|
|
94
|
+
PLATFORMS
|
|
95
|
+
ruby
|
|
96
|
+
|
|
97
|
+
DEPENDENCIES
|
|
98
|
+
activerecord-import
|
|
99
|
+
bullet!
|
|
100
|
+
mysql
|
|
101
|
+
perftools.rb
|
|
102
|
+
rails
|
|
103
|
+
rspec
|
|
104
|
+
sqlite3-ruby
|
|
105
|
+
watchr
|
data/Hacking.textile
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
h1. Bullet Overview for Developers
|
|
2
|
+
This file aims to give developers a quick tour of the bullet internals, making
|
|
3
|
+
it (hopefully) easier to extend or enhance the Bullet gem.
|
|
4
|
+
|
|
5
|
+
h2. General Control Flow aka. 10000 Meter View
|
|
6
|
+
When Rails is initialized, Bullet will extend ActiveRecord (and if you're using
|
|
7
|
+
Rails 2.x ActiveController too) with the relevant modules and methods found
|
|
8
|
+
in lib/bullet/active_recordX.rb and lib/bullet/action_controller2.rb. If you're
|
|
9
|
+
running Rails 3, Bullet will integrate itself as a middleware into the Rack
|
|
10
|
+
stack, so ActionController does not need to be extended.
|
|
11
|
+
|
|
12
|
+
The ActiveRecord extensions will call methods in a given detector class, when
|
|
13
|
+
certain methods are called.
|
|
14
|
+
|
|
15
|
+
Detector classes contain all the logic to recognize
|
|
16
|
+
a noteworthy event. If such an event is detected, an instance of the
|
|
17
|
+
corresponding Notification class is created and stored in a Set instance in the
|
|
18
|
+
main Bullet module (the 'notification collector').
|
|
19
|
+
|
|
20
|
+
Notification instances contain the message that will be displayed, and will
|
|
21
|
+
use a Presenter class to display their message to the user.
|
|
22
|
+
|
|
23
|
+
So the flow of a request goes like this:
|
|
24
|
+
1. Bullet.start_request is called, which resets all the detectors and empties
|
|
25
|
+
the notification collector
|
|
26
|
+
2. The request is handled by Rails, and the installed ActiveRecord extensions
|
|
27
|
+
trigger Detector callbacks
|
|
28
|
+
3. Detectors once called, will determine whether something noteworthy happend.
|
|
29
|
+
If yes, then a Notification is created and stored in the notification collector.
|
|
30
|
+
4. Rails finishes handling the request
|
|
31
|
+
5. For each notification in the collector, Bullet will iterate over each
|
|
32
|
+
Presenter and will try to generate an inline message that will be appended to
|
|
33
|
+
the generated response body.
|
|
34
|
+
6. The response is returned to the client.
|
|
35
|
+
7. Bullet will try to generate an out-of-channel message for each notification.
|
|
36
|
+
8. Bullet calls end_request for each detector.
|
|
37
|
+
9. Goto 1.
|
|
38
|
+
|
|
39
|
+
h2. Adding Notification Types
|
|
40
|
+
If you want to add more kinds of things that Bullet can detect, a little more
|
|
41
|
+
work is needed than if you were just adding a Presenter, but the concepts are
|
|
42
|
+
similar.
|
|
43
|
+
|
|
44
|
+
* Add the class to the DETECTORS constant in the main Bullet module
|
|
45
|
+
* Add (if needed) Rails monkey patches to Bullet.enable
|
|
46
|
+
* Add an autoload directive to lib/bullet/detector.rb
|
|
47
|
+
* Create a corresponding notification class in the Bullet::Notification namespace
|
|
48
|
+
* Add an autoload directive to lib/bullet/notification.rb
|
|
49
|
+
|
|
50
|
+
As a rule of thumb, you can assume that each Detector will have its own
|
|
51
|
+
Notification class. If you follow the principle of Separation of Concerns I
|
|
52
|
+
can't really think of an example where one would deviate from this rule.
|
|
53
|
+
|
|
54
|
+
Since the detection of pathological associations is a bit hairy, I'd recommend
|
|
55
|
+
having a look at the counter cache detector and associated notification to get
|
|
56
|
+
a feel for what is needed to get off the ground.
|
|
57
|
+
|
|
58
|
+
h3. Detectors
|
|
59
|
+
The only things you'll need to consider when building your Detector class is
|
|
60
|
+
that it will need to supply the .start_request, .end_request and .clear class
|
|
61
|
+
methods.
|
|
62
|
+
|
|
63
|
+
Simple implementations are provided by Bullet::Detector::Base for start_request
|
|
64
|
+
and end_request, you will have to supply your own clear method.
|
|
65
|
+
|
|
66
|
+
h3. Notifications
|
|
67
|
+
For notifications you will want to supply a #title and #body instance method,
|
|
68
|
+
and check to see if the #initialize and #full_notice methods in the
|
|
69
|
+
Bullet::Notification::Base class fit your needs.
|
data/MIT-LICENSE
CHANGED
data/README.textile
CHANGED
|
@@ -4,19 +4,22 @@ The Bullet plugin/gem is designed to help you increase your application's perfor
|
|
|
4
4
|
|
|
5
5
|
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.
|
|
6
6
|
|
|
7
|
-
The Bullet plugin/gem now supports rails 2.1, 2.2, 2.3 and 3.0
|
|
7
|
+
The Bullet plugin/gem now supports rails 2.1, 2.2, 2.3 and 3.0.
|
|
8
8
|
|
|
9
9
|
****************************************************************************
|
|
10
10
|
|
|
11
11
|
h2. Install
|
|
12
12
|
|
|
13
|
-
You can add Bullet to your Rails gem requirements:
|
|
14
|
-
<pre><code>config.gem 'bullet', :source => 'http://gemcutter.org'</code></pre>
|
|
15
|
-
|
|
16
13
|
You can install it as a gem:
|
|
17
14
|
<pre><code>
|
|
18
|
-
|
|
15
|
+
gem install bullet
|
|
19
16
|
</code></pre>
|
|
17
|
+
|
|
18
|
+
or add it into a Gemfile (Bundler):
|
|
19
|
+
<pre><code>
|
|
20
|
+
gem "bullet", :group => "development"
|
|
21
|
+
</code></code>
|
|
22
|
+
|
|
20
23
|
****************************************************************************
|
|
21
24
|
|
|
22
25
|
h2. Configuration
|
|
@@ -24,32 +27,30 @@ h2. Configuration
|
|
|
24
27
|
Bullet won't do ANYTHING unless you tell it to explicitly. Append to <code>config/environments/development.rb</code> initializer with the following code:
|
|
25
28
|
<pre><code>
|
|
26
29
|
config.after_initialize do
|
|
27
|
-
Bullet.enable = true
|
|
30
|
+
Bullet.enable = true
|
|
28
31
|
Bullet.alert = true
|
|
29
|
-
Bullet.bullet_logger = true
|
|
32
|
+
Bullet.bullet_logger = true
|
|
30
33
|
Bullet.console = true
|
|
31
34
|
Bullet.growl = true
|
|
35
|
+
Bullet.xmpp = { :account => 'bullets_account@jabber.org',
|
|
36
|
+
:password => 'bullets_password_for_jabber',
|
|
37
|
+
:receiver => 'your_account@jabber.org',
|
|
38
|
+
:show_online_status => true }
|
|
32
39
|
Bullet.rails_logger = true
|
|
33
40
|
Bullet.disable_browser_cache = true
|
|
34
41
|
end
|
|
35
42
|
</code></pre>
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
<pre><code>
|
|
39
|
-
begin
|
|
40
|
-
require 'ruby-growl'
|
|
41
|
-
Bullet.growl = true
|
|
42
|
-
rescue MissingSourceFile
|
|
43
|
-
end
|
|
44
|
-
</code></pre>
|
|
44
|
+
The notifier of bullet is a wrap of "uniform_notifier":https://github.com/flyerhzm/uniform_notifier
|
|
45
45
|
|
|
46
|
-
The code above will enable all
|
|
46
|
+
The code above will enable all six of the Bullet notification systems:
|
|
47
47
|
* <code>Bullet.enable</code>: enable Bullet plugin/gem, otherwise do nothing
|
|
48
48
|
* <code>Bullet.alert</code>: pop up a JavaScript alert in the browser
|
|
49
49
|
* <code>Bullet.bullet_logger</code>: log to the Bullet log file (Rails.root/log/bullet.log)
|
|
50
50
|
* <code>Bullet.rails_logger</code>: add warnings directly to the Rails log
|
|
51
51
|
* <code>Bullet.console</code>: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
|
|
52
52
|
* <code>Bullet.growl</code>: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
|
|
53
|
+
* <code>Bullet.xmpp</code>: 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.
|
|
53
54
|
* <code>Bullet.disable_browser_cache</code>: disable browser cache which usually causes unexpected problems
|
|
54
55
|
|
|
55
56
|
****************************************************************************
|
|
@@ -90,10 +91,10 @@ These two lines are notifications that unused eager loadings have been encounter
|
|
|
90
91
|
h2. Growl Support
|
|
91
92
|
|
|
92
93
|
To get Growl support up-and-running for Bullet, follow the steps below:
|
|
93
|
-
* Install the ruby-growl gem: <code>
|
|
94
|
+
* Install the ruby-growl gem: <code>gem install ruby-growl</code>
|
|
94
95
|
* Open the Growl preference pane in Systems Preferences
|
|
95
96
|
* Click the "Network" tab
|
|
96
|
-
* Make sure both "Listen for incoming notifications" and "Allow remote application registration" are checked. *Note*: If you set a password, you will need to set <code>Bullet.
|
|
97
|
+
* Make sure both "Listen for incoming notifications" and "Allow remote application registration" are checked. *Note*: If you set a password, you will need to set <code>Bullet.growl = { :password => 'growl password' }</code> in the config file.
|
|
97
98
|
* Restart Growl ("General" tab -> Stop Growl -> Start Growl)
|
|
98
99
|
* Boot up your application. Bullet will automatically send a Growl notification when Growl is turned on. If you do not see it when your application loads, make sure it is enabled in your initializer and double-check the steps above.
|
|
99
100
|
|
|
@@ -105,6 +106,17 @@ ruby-growl gem has an issue about md5 in ruby 1.9, if you use growl and ruby 1.9
|
|
|
105
106
|
|
|
106
107
|
****************************************************************************
|
|
107
108
|
|
|
109
|
+
h2. XMPP/Jabber Support
|
|
110
|
+
|
|
111
|
+
To get XMPP support up-and-running for Bullet, follow the steps below:
|
|
112
|
+
* Install the xmpp4r gem: <code>sudo gem install xmpp4r</code>
|
|
113
|
+
* Make both the bullet and the receipient account add each other as contacts.
|
|
114
|
+
This will require you to manually log into both accounts, add each other
|
|
115
|
+
as contact and confirm each others contact request.
|
|
116
|
+
* Boot up your application. Bullet will automatically send an XMPP notification when XMPP is turned on.
|
|
117
|
+
|
|
118
|
+
****************************************************************************
|
|
119
|
+
|
|
108
120
|
h2. Important
|
|
109
121
|
|
|
110
122
|
If you find bullet does not work for you, *please disable your browser's cache*.
|
|
@@ -134,8 +146,7 @@ end
|
|
|
134
146
|
|
|
135
147
|
after(:each)
|
|
136
148
|
if Bullet.enable?
|
|
137
|
-
Bullet.
|
|
138
|
-
Bullet.log_notification('Test: ')
|
|
149
|
+
Bullet.perform_out_of_channel_notifications
|
|
139
150
|
Bullet.end_request
|
|
140
151
|
end
|
|
141
152
|
end
|
|
@@ -155,6 +166,7 @@ h2. Links
|
|
|
155
166
|
|
|
156
167
|
h2. Contributors
|
|
157
168
|
|
|
169
|
+
sriedel did a lot of awesome refactors, added xmpp notification support, and added Hacking.textile about how to extend to bullet plugin.
|
|
158
170
|
flipsasser added Growl, console.log and Rails.log support, very awesome. And he also improved README.
|
|
159
171
|
rainux added group style console.log.
|
|
160
172
|
2collegebums added some great specs to generate red bar.
|
|
@@ -168,11 +180,11 @@ Bullet is designed to function as you browse through your application in develop
|
|
|
168
180
|
1. setup test environment
|
|
169
181
|
|
|
170
182
|
<pre><code>
|
|
171
|
-
$ rails
|
|
172
|
-
$ cd
|
|
173
|
-
$
|
|
174
|
-
$
|
|
175
|
-
$ rake db:migrate
|
|
183
|
+
$ rails new test_bullet
|
|
184
|
+
$ cd test_bullet
|
|
185
|
+
$ rails g scaffold post name:string
|
|
186
|
+
$ rails g scaffold comment name:string post_id:integer
|
|
187
|
+
$ bundle exec rake db:migrate
|
|
176
188
|
</code></pre>
|
|
177
189
|
|
|
178
190
|
2. change <code>app/model/post.rb</code> and <code>app/model/comment.rb</code>
|
|
@@ -187,7 +199,7 @@ class Comment < ActiveRecord::Base
|
|
|
187
199
|
end
|
|
188
200
|
</code></pre>
|
|
189
201
|
|
|
190
|
-
3. go to <code>
|
|
202
|
+
3. go to <code>rails c</code> and execute
|
|
191
203
|
|
|
192
204
|
<pre><code>
|
|
193
205
|
post1 = Post.create(:name => 'first')
|
|
@@ -203,8 +215,8 @@ post2.comments.create(:name => 'fourth')
|
|
|
203
215
|
<pre><code>
|
|
204
216
|
<% @posts.each do |post| %>
|
|
205
217
|
<tr>
|
|
206
|
-
<td><%=
|
|
207
|
-
<td><%= post.comments.
|
|
218
|
+
<td><%= post.name %></td>
|
|
219
|
+
<td><%= post.comments.map(&:name) %></td>
|
|
208
220
|
<td><%= link_to 'Show', post %></td>
|
|
209
221
|
<td><%= link_to 'Edit', edit_post_path(post) %></td>
|
|
210
222
|
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
|
|
@@ -215,7 +227,7 @@ post2.comments.create(:name => 'fourth')
|
|
|
215
227
|
5. add bullet gem to <code>Gemfile</code>
|
|
216
228
|
|
|
217
229
|
<pre><code>
|
|
218
|
-
gem "bullet"
|
|
230
|
+
gem "bullet"
|
|
219
231
|
</code></pre>
|
|
220
232
|
|
|
221
233
|
And run
|
|
@@ -239,7 +251,7 @@ end
|
|
|
239
251
|
7. start server
|
|
240
252
|
|
|
241
253
|
<pre><code>
|
|
242
|
-
$
|
|
254
|
+
$ rails s
|
|
243
255
|
</code></pre>
|
|
244
256
|
|
|
245
257
|
8. input http://localhost:3000/posts in browser, then you will see a popup alert box says
|
|
@@ -260,18 +272,18 @@ In the meanwhile, there's a log appended into <code>log/bullet.log</code> file
|
|
|
260
272
|
Post => [:comments]
|
|
261
273
|
Add to your finder: :include => [:comments]
|
|
262
274
|
2010-03-07 14:12:18[INFO] N+1 Query method call stack
|
|
263
|
-
/home/flyerhzm/
|
|
264
|
-
/home/flyerhzm/
|
|
265
|
-
/home/flyerhzm/
|
|
266
|
-
/home/flyerhzm/
|
|
275
|
+
/home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:14:in `_render_template__600522146_80203160_0'
|
|
276
|
+
/home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:11:in `each'
|
|
277
|
+
/home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:11:in `_render_template__600522146_80203160_0'
|
|
278
|
+
/home/flyerhzm/Downloads/test_bullet/app/controllers/posts_controller.rb:7:in `index'
|
|
267
279
|
</code></pre>
|
|
268
280
|
|
|
269
281
|
The generated SQLs are
|
|
270
282
|
|
|
271
283
|
<pre><code>
|
|
272
|
-
Post Load (1.0ms) SELECT * FROM "posts"
|
|
273
|
-
Comment Load (0.4ms) SELECT * FROM "comments" WHERE ("comments".post_id = 1)
|
|
274
|
-
Comment Load (0.3ms) SELECT * FROM "comments" WHERE ("comments".post_id = 2)
|
|
284
|
+
Post Load (1.0ms) SELECT * FROM "posts"
|
|
285
|
+
Comment Load (0.4ms) SELECT * FROM "comments" WHERE ("comments".post_id = 1)
|
|
286
|
+
Comment Load (0.3ms) SELECT * FROM "comments" WHERE ("comments".post_id = 2)
|
|
275
287
|
</code></pre>
|
|
276
288
|
|
|
277
289
|
|
|
@@ -284,8 +296,8 @@ The generated SQLs are
|
|
|
284
296
|
respond_to do |format|
|
|
285
297
|
format.html # index.html.erb
|
|
286
298
|
format.xml { render :xml => @posts }
|
|
287
|
-
end
|
|
288
|
-
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
289
301
|
</code></pre>
|
|
290
302
|
|
|
291
303
|
10. refresh http://localhost:3000/posts page, no alert box and no log appended.
|
|
@@ -293,8 +305,8 @@ The generated SQLs are
|
|
|
293
305
|
The generated SQLs are
|
|
294
306
|
|
|
295
307
|
<pre><code>
|
|
296
|
-
Post Load (0.5ms) SELECT * FROM "posts"
|
|
297
|
-
Comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE ("comments".post_id IN (1,2))
|
|
308
|
+
Post Load (0.5ms) SELECT * FROM "posts"
|
|
309
|
+
Comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE ("comments".post_id IN (1,2))
|
|
298
310
|
</code></pre>
|
|
299
311
|
|
|
300
312
|
a N+1 query fixed. Cool!
|
|
@@ -308,14 +320,14 @@ a N+1 query fixed. Cool!
|
|
|
308
320
|
respond_to do |format|
|
|
309
321
|
format.html # index.html.erb
|
|
310
322
|
format.xml { render :xml => @posts }
|
|
311
|
-
end
|
|
312
|
-
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
313
325
|
</code></pre>
|
|
314
326
|
|
|
315
327
|
<pre><code>
|
|
316
328
|
<% @posts.each do |post| %>
|
|
317
329
|
<tr>
|
|
318
|
-
<td><%=
|
|
330
|
+
<td><%= post.name %></td>
|
|
319
331
|
<td><%= link_to 'Show', post %></td>
|
|
320
332
|
<td><%= link_to 'Edit', edit_post_path(post) %></td>
|
|
321
333
|
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
|
|
@@ -348,15 +360,15 @@ Remove from your finder: :include => [:comments]
|
|
|
348
360
|
respond_to do |format|
|
|
349
361
|
format.html # index.html.erb
|
|
350
362
|
format.xml { render :xml => @posts }
|
|
351
|
-
end
|
|
352
|
-
end
|
|
363
|
+
end
|
|
364
|
+
end
|
|
353
365
|
</code></pre>
|
|
354
366
|
|
|
355
367
|
<pre><code>
|
|
356
368
|
<% @posts.each do |post| %>
|
|
357
369
|
<tr>
|
|
358
|
-
<td><%=
|
|
359
|
-
<td><%=
|
|
370
|
+
<td><%= post.name %></td>
|
|
371
|
+
<td><%= post.comments.size %></td>
|
|
360
372
|
<td><%= link_to 'Show', post %></td>
|
|
361
373
|
<td><%= link_to 'Edit', edit_post_path(post) %></td>
|
|
362
374
|
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></td>
|
|
@@ -381,4 +393,4 @@ In the meanwhile, there's a log appended into <code>log/bullet.log</code> file.
|
|
|
381
393
|
****************************************************************************
|
|
382
394
|
|
|
383
395
|
|
|
384
|
-
Copyright (c) 2009 Richard Huang (flyerhzm@gmail.com), released under the MIT license
|
|
396
|
+
Copyright (c) 2009 - 2011 Richard Huang (flyerhzm@gmail.com), released under the MIT license
|