bullet 4.11.3 → 4.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ca96bf9ce0ec1f8610db4044ca48bc25ebf8ded
4
- data.tar.gz: b2f6067c61713e0c0bb5c868d7f8e5464e09476c
3
+ metadata.gz: b201e99b1db5ea0ae016eb415b8bdcb2141a0321
4
+ data.tar.gz: 072c423687b8482273549f30c2538edec5c3c03f
5
5
  SHA512:
6
- metadata.gz: 4d6ceb5f5ad0c7357a741bbd04b42bd188e38802a7a448aca7e289166570947a9941a224a306634ccd7e4ad99279c2e9dd1692935526dc0ef6b16fbdee26a0c3
7
- data.tar.gz: fd48101ec26800797c4cd834905b3f8b1666631a39ac3f42f088430b82611d2b144daefc307fcc0cfffb07d788971b5e4d155269df642e7f2b2b83edde10128b
6
+ metadata.gz: 624bfcc8a8f2044699d19e598729cba0bf858e054002b435a31cce643d1bc3834139dad14ea510ef573a31059ce13f4b5c1dd892404645cca8d77e47264db794
7
+ data.tar.gz: ffaf8125f6797fd85b42be44f645e835796d623bc8b656662b8bd7387ac3b92882d4f2daaf2c50c04aced38113d7c96fbd8b3bdf631bd532c0a02663e221e1d1
@@ -1,11 +1,12 @@
1
1
  # Next Release
2
2
 
3
- ## 4.12.0 (not released yet)
3
+ ## 4.12.0
4
4
 
5
- * Use primary_key rather than id for bullet_ar_key
5
+ * Fix false n+1 queries caused by inversed objects.
6
+ * Replace .id with .primary_key_value
6
7
  * Rename bullet_ar_key to bullet_key
7
8
  * Fix rails sse detect
8
- * Fix bullet in rails test
9
+ * Fix bullet using in test environment
9
10
  * Memoize whoami
10
11
 
11
12
  ## 4.11.0 (06/24/2014)
@@ -5,7 +5,7 @@ gemspec
5
5
  gem 'rails', '~> 4.0.5'
6
6
  gem 'sqlite3', platforms: [:ruby]
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
- gem 'mongoid', '~> 4.0.0.beta2'
8
+ gem 'mongoid', '~> 4.0.0'
9
9
 
10
10
  gem "rspec"
11
11
  gem "guard"
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 3.2.18'
5
+ gem 'rails', '~> 3.2.19'
6
6
  gem 'sqlite3', platforms: [:ruby]
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 4.0.5'
5
+ gem 'rails', '~> 4.0.8'
6
6
  gem 'sqlite3', platforms: [:ruby]
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 4.1.1'
5
+ gem 'rails', '~> 4.1.4'
6
6
  gem 'sqlite3'
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
data/README.md CHANGED
@@ -60,7 +60,7 @@ config.after_initialize do
60
60
  end
61
61
  ```
62
62
 
63
- The notifier of bullet is a wrap of [uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
63
+ The notifier of Bullet is a wrap of [uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
64
64
 
65
65
  The code above will enable all seven of the Bullet notification systems:
66
66
  * `Bullet.enable`: enable Bullet gem, otherwise do nothing
@@ -70,25 +70,31 @@ The code above will enable all seven of the Bullet notification systems:
70
70
  * `Bullet.airbrake`: add notifications to airbrake
71
71
  * `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
72
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.
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
74
  * `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
75
75
  * `Bullet.add_footer`: adds the details in the bottom left corner of the page
76
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
77
 
78
- Bullet also allows you to disable n_plus_one_query, unused_eager_loading
79
- and counter_cache detectors respectively.
78
+ Bullet also allows you to disable any of its detectors.
80
79
 
81
80
  ```ruby
82
- Bullet.n_plus_one_query_enable = false
81
+ # Each of these settings defaults to true
82
+
83
+ # Detect N+1 queries
84
+ Bullet.n_plus_one_query_enable = false
85
+
86
+ # Detect eager-loaded associations which are not used
83
87
  Bullet.unused_eager_loading_enable = false
84
- Bullet.counter_cache_enable = false
88
+
89
+ # Detect unnecessary COUNT queries which could be avoided
90
+ # with a counter_cache
91
+ Bullet.counter_cache_enable = false
85
92
  ```
86
93
 
87
94
  ## Whitelist
88
95
 
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
96
+ Sometimes Bullet 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:
92
98
 
93
99
  ```ruby
94
100
  Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments
@@ -136,13 +142,13 @@ see [https://github.com/flyerhzm/uniform_notifier](https://github.com/flyerhzm/u
136
142
 
137
143
  ## Important
138
144
 
139
- If you find bullet does not work for you, *please disable your browser's cache*.
145
+ If you find Bullet does not work for you, *please disable your browser's cache*.
140
146
 
141
147
  ## Advanced
142
148
 
143
149
  ### Profile a job
144
150
 
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
151
+ 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
152
 
147
153
  ```ruby
148
154
  Bullet.profile do
@@ -153,7 +159,7 @@ warnings = Bullet.warnings
153
159
 
154
160
  ### Work with sinatra
155
161
 
156
- Configure and use bullet rack
162
+ Configure and use `Bullet::Rack`
157
163
 
158
164
  ```ruby
159
165
  configure :development do
@@ -165,7 +171,7 @@ end
165
171
 
166
172
  ### Run in tests
167
173
 
168
- First you need to enable bullet in test environment.
174
+ First you need to enable Bullet in test environment.
169
175
 
170
176
  ```ruby
171
177
  # config/environments/test.rb
@@ -176,7 +182,7 @@ config.after_initialize do
176
182
  end
177
183
  ```
178
184
 
179
- Then wrap each test in bullet api.
185
+ Then wrap each test in Bullet api.
180
186
 
181
187
  ```ruby
182
188
  # spec/spec_helper.rb
@@ -194,18 +200,18 @@ end
194
200
 
195
201
  ## Debug Mode
196
202
 
197
- Bullet outputs some details info, to enable debug mode, set DEBUG=true
198
- env.
203
+ Bullet outputs some details info, to enable debug mode, set
204
+ `BULLET_DEBUG=true` env.
199
205
 
200
206
  ## Contributors
201
207
 
202
208
  [https://github.com/flyerhzm/bullet/contributors](https://github.com/flyerhzm/bullet/contributors)
203
209
 
204
- ## Step by step example
210
+ ## Demo
205
211
 
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.
212
+ Bullet 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.
207
213
 
208
- 1\. setup test environment
214
+ 1\. Create an example application
209
215
 
210
216
  ```
211
217
  $ rails new test_bullet
@@ -215,7 +221,7 @@ $ rails g scaffold comment name:string post_id:integer
215
221
  $ bundle exec rake db:migrate
216
222
  ```
217
223
 
218
- 2\. change `app/model/post.rb` and `app/model/comment.rb`
224
+ 2\. Change `app/model/post.rb` and `app/model/comment.rb`
219
225
 
220
226
  ```ruby
221
227
  class Post < ActiveRecord::Base
@@ -227,7 +233,7 @@ class Comment < ActiveRecord::Base
227
233
  end
228
234
  ```
229
235
 
230
- 3\. go to `rails c` and execute
236
+ 3\. Go to `rails c` and execute
231
237
 
232
238
  ```ruby
233
239
  post1 = Post.create(:name => 'first')
@@ -238,7 +244,7 @@ post2.comments.create(:name => 'third')
238
244
  post2.comments.create(:name => 'fourth')
239
245
  ```
240
246
 
241
- 4\. change the `app/views/posts/index.html.erb` to produce a N+1 query
247
+ 4\. Change the `app/views/posts/index.html.erb` to produce a N+1 query
242
248
 
243
249
  ```
244
250
  <% @posts.each do |post| %>
@@ -252,7 +258,7 @@ post2.comments.create(:name => 'fourth')
252
258
  <% end %>
253
259
  ```
254
260
 
255
- 5\. add bullet gem to `Gemfile`
261
+ 5\. Add the `bullet` gem to the `Gemfile`
256
262
 
257
263
  ```ruby
258
264
  gem "bullet"
@@ -264,7 +270,7 @@ And run
264
270
  bundle install
265
271
  ```
266
272
 
267
- 6\. enable the bullet gem in development, add a line to
273
+ 6\. enable the Bullet gem in development, add a line to
268
274
  `config/environments/development.rb`
269
275
 
270
276
  ```ruby
@@ -279,13 +285,13 @@ config.after_initialize do
279
285
  end
280
286
  ```
281
287
 
282
- 7\. start server
288
+ 7\. Start the server
283
289
 
284
290
  ```
285
291
  $ rails s
286
292
  ```
287
293
 
288
- 8\. input http://localhost:3000/posts in browser, then you will see a popup alert box says
294
+ 8\. Visit `http://localhost:3000/posts` in browser, and you will see a popup alert box that says
289
295
 
290
296
  ```
291
297
  The request has unused preload associations as follows:
@@ -294,7 +300,7 @@ The request has N+1 queries as follows:
294
300
  model: Post => associations: [comment]
295
301
  ```
296
302
 
297
- which means there is a N+1 query from post object to comments associations.
303
+ which means there is a N+1 query from the Post object to its Comment association.
298
304
 
299
305
  In the meanwhile, there's a log appended into `log/bullet.log` file
300
306
 
@@ -309,7 +315,7 @@ In the meanwhile, there's a log appended into `log/bullet.log` file
309
315
  /home/flyerhzm/Downloads/test_bullet/app/controllers/posts_controller.rb:7:in `index'
310
316
  ```
311
317
 
312
- The generated SQLs are
318
+ The generated SQL is:
313
319
 
314
320
  ```
315
321
  Post Load (1.0ms) SELECT * FROM "posts"
@@ -317,8 +323,7 @@ Comment Load (0.4ms) SELECT * FROM "comments" WHERE ("comments".post_id = 1)
317
323
  Comment Load (0.3ms) SELECT * FROM "comments" WHERE ("comments".post_id = 2)
318
324
  ```
319
325
 
320
-
321
- 9\. fix the N+1 query, change `app/controllers/posts_controller.rb` file
326
+ 9\. To fix the N+1 query, change `app/controllers/posts_controller.rb` file
322
327
 
323
328
  ```ruby
324
329
  def index
@@ -331,18 +336,18 @@ def index
331
336
  end
332
337
  ```
333
338
 
334
- 10\. refresh http://localhost:3000/posts page, no alert box and no log appended.
339
+ 10\. Refresh `http://localhost:3000/posts`. Now there's no alert box and nothing new in the log.
335
340
 
336
- The generated SQLs are
341
+ The generated SQL is:
337
342
 
338
343
  ```
339
344
  Post Load (0.5ms) SELECT * FROM "posts"
340
345
  Comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE ("comments".post_id IN (1,2))
341
346
  ```
342
347
 
343
- a N+1 query fixed. Cool!
348
+ N+1 query fixed. Cool!
344
349
 
345
- 11\. now simulate unused eager loading. Change
350
+ 11\. Now simulate unused eager loading. Change
346
351
  `app/controllers/posts_controller.rb` and
347
352
  `app/views/posts/index.html.erb`
348
353
 
@@ -368,7 +373,7 @@ end
368
373
  <% end %>
369
374
  ```
370
375
 
371
- 12\. refresh http://localhost:3000/posts page, then you will see a popup alert box says
376
+ 12\. Refresh `http://localhost:3000/posts`, and you will see a popup alert box that says
372
377
 
373
378
  ```
374
379
  The request has unused preload associations as follows:
@@ -377,14 +382,14 @@ The request has N+1 queries as follows:
377
382
  None
378
383
  ```
379
384
 
380
- In the meanwhile, there's a log appended into `log/bullet.log` file
385
+ Meanwhile, there's a line appended to `log/bullet.log`
381
386
 
382
387
  ```
383
388
  2009-08-25 21:13:22[INFO] Unused preload associations: PATH_INFO: /posts; model: Post => associations: [comments]·
384
389
  Remove from your finder: :include => [:comments]
385
390
  ```
386
391
 
387
- 13\. simulate counter_cache. Change `app/controllers/posts_controller.rb`
392
+ 13\. Simulate counter_cache. Change `app/controllers/posts_controller.rb`
388
393
  and `app/views/posts/index.html.erb`
389
394
 
390
395
  ```ruby
@@ -410,19 +415,18 @@ end
410
415
  <% end %>
411
416
  ```
412
417
 
413
- 14\. refresh http://localhost:3000/posts page, then you will see a popup alert box says
418
+ 14\. Refresh `http://localhost:3000/posts`, then you will see a popup alert box that says
414
419
 
415
420
  ```
416
421
  Need counter cache
417
422
  Post => [:comments]
418
423
  ```
419
424
 
420
- In the meanwhile, there's a log appended into `log/bullet.log` file.
425
+ Meanwhile, there's a line appended to `log/bullet.log`
421
426
 
422
427
  ```
423
428
  2009-09-11 10:07:10[INFO] Need Counter Cache
424
429
  Post => [:comments]
425
430
  ```
426
431
 
427
-
428
432
  Copyright (c) 2009 - 2014 Richard Huang (flyerhzm@gmail.com), released under the MIT license
@@ -96,7 +96,7 @@ module Bullet
96
96
  end
97
97
 
98
98
  def debug(title, message)
99
- puts "[Bullet][#{title}] #{message}" if ENV['DEBUG'] == 'true'
99
+ puts "[Bullet][#{title}] #{message}" if ENV['BULLET_DEBUG'] == 'true'
100
100
  end
101
101
 
102
102
  def start_request
@@ -107,6 +107,7 @@ module Bullet
107
107
  Thread.current[:bullet_call_object_associations] = Bullet::Registry::Base.new
108
108
  Thread.current[:bullet_possible_objects] = Bullet::Registry::Object.new
109
109
  Thread.current[:bullet_impossible_objects] = Bullet::Registry::Object.new
110
+ Thread.current[:bullet_inversed_objects] = Bullet::Registry::Base.new
110
111
  Thread.current[:bullet_eager_loadings] = Bullet::Registry::Association.new
111
112
 
112
113
  Thread.current[:bullet_counter_possible_objects] ||= Bullet::Registry::Object.new
@@ -118,9 +119,10 @@ module Bullet
118
119
  Thread.current[:bullet_notification_collector] = nil
119
120
 
120
121
  Thread.current[:bullet_object_associations] = nil
122
+ Thread.current[:bullet_call_object_associations] = nil
121
123
  Thread.current[:bullet_possible_objects] = nil
122
124
  Thread.current[:bullet_impossible_objects] = nil
123
- Thread.current[:bullet_call_object_associations] = nil
125
+ Thread.current[:bullet_inversed_objects] = nil
124
126
  Thread.current[:bullet_eager_loadings] = nil
125
127
 
126
128
  Thread.current[:bullet_counter_possible_objects] = nil
@@ -119,7 +119,7 @@ module Bullet
119
119
  alias_method :origin_set_inverse_instance, :set_inverse_instance
120
120
  def set_inverse_instance(record, instance)
121
121
  if record && we_can_set_the_inverse_on_this?(record)
122
- Bullet::Detector::NPlusOneQuery.add_impossible_object(record)
122
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(record, @reflection.inverse_of.name)
123
123
  end
124
124
  origin_set_inverse_instance(record, instance)
125
125
  end
@@ -108,7 +108,7 @@ module Bullet
108
108
  alias_method :origin_set_inverse_instance, :set_inverse_instance
109
109
  def set_inverse_instance(record)
110
110
  if record && invertible_for?(record)
111
- Bullet::Detector::NPlusOneQuery.add_impossible_object(record)
111
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(record, inverse_reflection_for(record).name)
112
112
  end
113
113
  origin_set_inverse_instance(record)
114
114
  end
@@ -98,22 +98,12 @@ module Bullet
98
98
  alias_method :origin_reader, :reader
99
99
  def reader(force_reload = false)
100
100
  result = origin_reader(force_reload)
101
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
101
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless @inversed
102
102
  Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
103
103
  result
104
104
  end
105
105
  end
106
106
 
107
- ::ActiveRecord::Associations::Association.class_eval do
108
- alias_method :origin_set_inverse_instance, :set_inverse_instance
109
- def set_inverse_instance(record)
110
- if record && invertible_for?(record)
111
- Bullet::Detector::NPlusOneQuery.add_impossible_object(record)
112
- end
113
- origin_set_inverse_instance(record)
114
- end
115
- end
116
-
117
107
  ::ActiveRecord::Associations::HasManyAssociation.class_eval do
118
108
  alias_method :origin_has_cached_counter?, :has_cached_counter?
119
109
 
@@ -27,6 +27,7 @@ module Bullet
27
27
  def preloaders_on(association, records, scope)
28
28
  if records.first.class.name !~ /^HABTM_/
29
29
  records.each do |record|
30
+ next unless record
30
31
  Bullet::Detector::Association.add_object_associations(record, association)
31
32
  end
32
33
  Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
@@ -5,7 +5,7 @@ module Bullet
5
5
  def add_object_associations(object, associations)
6
6
  return unless Bullet.start?
7
7
  return if !Bullet.n_plus_one_query_enable? && !Bullet.unused_eager_loading_enable?
8
- return unless object.id
8
+ return unless object.primary_key_value
9
9
 
10
10
  Bullet.debug("Detector::Association#add_object_associations", "object: #{object.bullet_key}, associations: #{associations}")
11
11
  object_associations.add(object.bullet_key, associations)
@@ -14,7 +14,7 @@ module Bullet
14
14
  def add_call_object_associations(object, associations)
15
15
  return unless Bullet.start?
16
16
  return if !Bullet.n_plus_one_query_enable? && !Bullet.unused_eager_loading_enable?
17
- return unless object.id
17
+ return unless object.primary_key_value
18
18
 
19
19
  Bullet.debug("Detector::Association#add_call_object_associations", "object: #{object.bullet_key}, associations: #{associations}")
20
20
  call_object_associations.add(object.bullet_key, associations)
@@ -48,13 +48,19 @@ module Bullet
48
48
  # impossible_objects keep the class to objects relationships
49
49
  # that the objects may not cause N+1 query.
50
50
  # e.g. { Post => ["Post:1", "Post:2"] }
51
- # Notice: impossible_objects are not accurate,
52
51
  # if find collection returns only one object, then the object is impossible object,
53
52
  # impossible_objects are used to avoid treating 1+1 query to N+1 query.
54
53
  def impossible_objects
55
54
  Thread.current[:bullet_impossible_objects]
56
55
  end
57
56
 
57
+ # inversed_objects keeps object relationships
58
+ # that association is inversed.
59
+ # e.g. { "Comment:1" => ["post"] }
60
+ def inversed_objects
61
+ Thread.current[:bullet_inversed_objects]
62
+ end
63
+
58
64
  # eager_loadings keep the object relationships
59
65
  # that the associations are preloaded by find :include.
60
66
  # e.g. { ["Post:1", "Post:2"] => [:comments, :user] }
@@ -5,7 +5,7 @@ module Bullet
5
5
  def add_counter_cache(object, associations)
6
6
  return unless Bullet.start?
7
7
  return unless Bullet.counter_cache_enable?
8
- return unless object.id
8
+ return unless object.primary_key_value
9
9
 
10
10
  Bullet.debug("Detector::CounterCache#add_counter_cache", "object: #{object.bullet_key}, associations: #{associations}")
11
11
  if conditions_met?(object.bullet_key, associations)
@@ -17,7 +17,7 @@ module Bullet
17
17
  return unless Bullet.start?
18
18
  return unless Bullet.counter_cache_enable?
19
19
  objects = Array(object_or_objects)
20
- return if objects.map(&:id).compact.empty?
20
+ return if objects.map(&:primary_key_value).compact.empty?
21
21
 
22
22
  Bullet.debug("Detector::CounterCache#add_possible_objects", "objects: #{objects.map(&:bullet_key).join(', ')}")
23
23
  objects.each { |object| possible_objects.add object.bullet_key }
@@ -26,7 +26,7 @@ module Bullet
26
26
  def add_impossible_object(object)
27
27
  return unless Bullet.start?
28
28
  return unless Bullet.counter_cache_enable?
29
- return unless object.id
29
+ return unless object.primary_key_value
30
30
 
31
31
  Bullet.debug("Detector::CounterCache#add_impossible_object", "object: #{object.bullet_key}")
32
32
  impossible_objects.add object.bullet_key
@@ -10,7 +10,8 @@ module Bullet
10
10
  # if it is, keeps this unpreload associations and caller.
11
11
  def call_association(object, associations)
12
12
  return unless Bullet.start?
13
- return unless object.id
13
+ return unless object.primary_key_value
14
+ return if inversed_objects.include?(object.bullet_key, associations)
14
15
  add_call_object_associations(object, associations)
15
16
 
16
17
  Bullet.debug("Detector::NPlusOneQuery#call_association", "object: #{object.bullet_key}, associations: #{associations}")
@@ -24,7 +25,7 @@ module Bullet
24
25
  return unless Bullet.start?
25
26
  return unless Bullet.n_plus_one_query_enable?
26
27
  objects = Array(object_or_objects)
27
- return if objects.map(&:id).compact.empty?
28
+ return if objects.map(&:primary_key_value).compact.empty?
28
29
 
29
30
  Bullet.debug("Detector::NPlusOneQuery#add_possible_objects", "objects: #{objects.map(&:bullet_key).join(', ')}")
30
31
  objects.each { |object| possible_objects.add object.bullet_key }
@@ -33,12 +34,21 @@ module Bullet
33
34
  def add_impossible_object(object)
34
35
  return unless Bullet.start?
35
36
  return unless Bullet.n_plus_one_query_enable?
36
- return unless object.id
37
+ return unless object.primary_key_value
37
38
 
38
39
  Bullet.debug("Detector::NPlusOneQuery#add_impossible_object", "object: #{object.bullet_key}")
39
40
  impossible_objects.add object.bullet_key
40
41
  end
41
42
 
43
+ def add_inversed_object(object, association)
44
+ return unless Bullet.start?
45
+ return unless Bullet.n_plus_one_query_enable?
46
+ return unless object.primary_key_value
47
+
48
+ Bullet.debug("Detector::NPlusOneQuery#add_inversed_object", "object: #{object.bullet_key}, association: #{association}")
49
+ inversed_objects.add object.bullet_key, association
50
+ end
51
+
42
52
  private
43
53
  def create_notification(callers, klazz, associations)
44
54
  notify_associations = Array(associations) - Bullet.get_whitelist_associations(:n_plus_one_query, klazz)
@@ -22,7 +22,7 @@ module Bullet
22
22
  def add_eager_loadings(objects, associations)
23
23
  return unless Bullet.start?
24
24
  return unless Bullet.unused_eager_loading_enable?
25
- return if objects.map(&:id).compact.empty?
25
+ return if objects.map(&:primary_key_value).compact.empty?
26
26
 
27
27
  Bullet.debug("Detector::UnusedEagerLoading#add_eager_loadings", "objects: #{objects.map(&:bullet_key).join(', ')}, associations: #{associations}")
28
28
  bullet_keys = objects.map(&:bullet_key)
@@ -1,9 +1,13 @@
1
1
  class Object
2
2
  def bullet_key
3
+ [self.class, self.primary_key_value].join(':')
4
+ end
5
+
6
+ def primary_key_value
3
7
  if self.class.respond_to?(:primary_key) && self.class.primary_key
4
- "#{self.class}:#{self.send self.class.primary_key}"
8
+ self.send self.class.primary_key
5
9
  else
6
- "#{self.class}:#{self.id}"
10
+ self.id
7
11
  end
8
12
  end
9
13
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Bullet
3
- VERSION = "4.11.3"
3
+ VERSION = "4.12.0"
4
4
  end
@@ -14,4 +14,18 @@ describe Object do
14
14
  end
15
15
  end
16
16
  end
17
+
18
+ context "primary_key_value" do
19
+ it "should return id" do
20
+ post = Post.first
21
+ expect(post.primary_key_value).to eq(post.id)
22
+ end
23
+
24
+ it "should return primary key value" do
25
+ post = Post.first
26
+ Post.primary_key = 'name'
27
+ expect(post.primary_key_value).to eq(post.name)
28
+ Post.primary_key = 'id'
29
+ end
30
+ end
17
31
  end
@@ -39,7 +39,7 @@ if !mongoid? && active_record3?
39
39
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
40
40
  end
41
41
 
42
- it "should detect non preload comment => post with inverse_of" do
42
+ it "should not detect non preload comment => post with inverse_of" do
43
43
  Post.includes(:comments).each do |post|
44
44
  post.comments.each do |comment|
45
45
  comment.name
@@ -1,5 +1,5 @@
1
1
  class Category < ActiveRecord::Base
2
- has_many :posts
2
+ has_many :posts, inverse_of: :category
3
3
  has_many :entries
4
4
 
5
5
  has_many :submissions
@@ -1,7 +1,7 @@
1
1
  class Post < ActiveRecord::Base
2
2
  extend Bullet::Dependency
3
3
 
4
- belongs_to :category
4
+ belongs_to :category, inverse_of: :posts
5
5
  belongs_to :writer
6
6
  has_many :comments, inverse_of: :post
7
7
 
@@ -65,7 +65,7 @@ if active_record?
65
65
  end
66
66
  end
67
67
 
68
- if ENV["LOG"]
68
+ if ENV["BULLET_LOG"]
69
69
  require 'logger'
70
70
  ActiveRecord::Base.logger = Logger.new(STDOUT)
71
71
  end
@@ -96,7 +96,7 @@ if mongoid?
96
96
  end
97
97
  end
98
98
 
99
- if ENV["LOG"]
99
+ if ENV["BULLET_LOG"]
100
100
  Mongoid.logger = Logger.new(STDOUT)
101
101
  Moped.logger = Logger.new(STDOUT)
102
102
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.11.3
4
+ version: 4.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-29 00:00:00.000000000 Z
11
+ date: 2014-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport