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.
Files changed (49) hide show
  1. data/.gitignore +9 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +2 -0
  4. data/.rvmrc.example +2 -0
  5. data/.watchr +24 -0
  6. data/Gemfile +15 -0
  7. data/Gemfile.lock +105 -0
  8. data/Hacking.textile +69 -0
  9. data/MIT-LICENSE +1 -1
  10. data/README.textile +61 -49
  11. data/README_for_rails2.textile +41 -42
  12. data/Rakefile +40 -29
  13. data/bullet.gemspec +17 -60
  14. data/lib/bullet/action_controller2.rb +6 -6
  15. data/lib/bullet/active_record2.rb +17 -16
  16. data/lib/bullet/active_record3.rb +17 -25
  17. data/lib/bullet/active_record31.rb +96 -0
  18. data/lib/bullet/detector/association.rb +144 -0
  19. data/lib/bullet/detector/base.rb +12 -0
  20. data/lib/bullet/detector/counter.rb +43 -0
  21. data/lib/bullet/detector/n_plus_one_query.rb +39 -0
  22. data/lib/bullet/detector/unused_eager_association.rb +41 -0
  23. data/lib/bullet/detector.rb +9 -0
  24. data/lib/bullet/notification/base.rb +61 -0
  25. data/lib/bullet/notification/counter_cache.rb +13 -0
  26. data/lib/bullet/notification/n_plus_one_query.rb +32 -0
  27. data/lib/bullet/notification/unused_eager_loading.rb +14 -0
  28. data/lib/bullet/notification.rb +4 -79
  29. data/lib/bullet/notification_collector.rb +25 -0
  30. data/lib/bullet/rack.rb +44 -0
  31. data/lib/bullet/registry/association.rb +15 -0
  32. data/lib/bullet/registry/base.rb +37 -0
  33. data/lib/bullet/registry/object.rb +15 -0
  34. data/lib/bullet/registry.rb +7 -0
  35. data/lib/bullet/version.rb +5 -0
  36. data/lib/bullet.rb +64 -43
  37. data/perf/benchmark.rb +106 -0
  38. data/spec/bullet/association_for_chris_spec.rb +6 -6
  39. data/spec/bullet/association_for_peschkaj_spec.rb +6 -6
  40. data/spec/bullet/association_spec.rb +140 -294
  41. data/spec/bullet/counter_spec.rb +10 -10
  42. data/spec/spec_helper.rb +51 -17
  43. metadata +72 -57
  44. data/VERSION +0 -1
  45. data/lib/bullet/association.rb +0 -294
  46. data/lib/bullet/counter.rb +0 -101
  47. data/lib/bullet/logger.rb +0 -9
  48. data/lib/bulletware.rb +0 -42
  49. data/spec/spec.opts +0 -3
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ log/**
2
+ pkg/**
3
+ .DS_Store
4
+ lib/.DS_Store
5
+ .*.swp
6
+ coverage.data
7
+ tags
8
+ .bundle
9
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format nested
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm_gemset_create_on_use_flag=1
2
+ rvm gemset use bullet
data/.rvmrc.example ADDED
@@ -0,0 +1,2 @@
1
+ rvm_gemset_create_on_use_flag=1
2
+ rvm gemset use bullet
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Richard Huang (flyerhzm@gmail.com)
1
+ Copyright (c) 2009 - 2010 Richard Huang (flyerhzm@gmail.com)
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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, tested in rails 2.1.2, 2.2.2, 2.3.2 and 3.0.0.beta.
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
- sudo gem install bullet --pre
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
- It is recommended to config growl notification as follows if your collaborators are not using MacOS
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 five of the Bullet notification systems:
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>sudo gem install ruby-growl</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.growl_password = 'your_growl_password</code>' in the config file.
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.growl_notification
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 test
172
- $ cd test
173
- $ script/rails g scaffold post name:string
174
- $ script/rails g scaffold comment name:string post_id:integer
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>script/rails c</code> and execute
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><%=h post.name %></td>
207
- <td><%= post.comments.collect(&:name) %></td>
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", "2.0.0.beta.2"
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
- $ script/rails s
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/NetBeansProjects/test_bullet2/app/views/posts/index.html.erb:14:in `_render_template__600522146_80203160_0'
264
- /home/flyerhzm/NetBeansProjects/test_bullet2/app/views/posts/index.html.erb:11:in `each'
265
- /home/flyerhzm/NetBeansProjects/test_bullet2/app/views/posts/index.html.erb:11:in `_render_template__600522146_80203160_0'
266
- /home/flyerhzm/NetBeansProjects/test_bullet2/app/controllers/posts_controller.rb:7:in `index'
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><%=h post.name %></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><%=h post.name %></td>
359
- <td><%=h post.comments.size %></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