bullet 5.1.0 → 5.4.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -13
  3. data/CHANGELOG.md +20 -2
  4. data/Gemfile.mongoid-2.4 +0 -2
  5. data/Gemfile.mongoid-2.5 +0 -2
  6. data/Gemfile.mongoid-2.6 +0 -2
  7. data/Gemfile.mongoid-2.7 +0 -2
  8. data/Gemfile.mongoid-2.8 +0 -2
  9. data/Gemfile.mongoid-3.0 +0 -2
  10. data/Gemfile.mongoid-3.1 +0 -2
  11. data/Gemfile.mongoid-4.0 +0 -2
  12. data/Gemfile.mongoid-5.0 +0 -2
  13. data/Gemfile.rails-3.0 +0 -2
  14. data/Gemfile.rails-3.1 +0 -2
  15. data/Gemfile.rails-3.2 +0 -2
  16. data/Gemfile.rails-4.0 +0 -2
  17. data/Gemfile.rails-4.1 +0 -2
  18. data/Gemfile.rails-4.2 +0 -2
  19. data/Gemfile.rails-5.0 +1 -3
  20. data/README.md +5 -4
  21. data/lib/bullet/active_record3.rb +34 -3
  22. data/lib/bullet/active_record3x.rb +34 -3
  23. data/lib/bullet/active_record4.rb +34 -3
  24. data/lib/bullet/active_record41.rb +19 -0
  25. data/lib/bullet/active_record42.rb +37 -0
  26. data/lib/bullet/active_record5.rb +61 -48
  27. data/lib/bullet/dependency.rb +7 -1
  28. data/lib/bullet/detector/n_plus_one_query.rb +1 -15
  29. data/lib/bullet/detector/unused_eager_loading.rb +6 -3
  30. data/lib/bullet/notification/unused_eager_loading.rb +12 -0
  31. data/lib/bullet/rack.rb +2 -2
  32. data/lib/bullet/stack_trace_filter.rb +34 -0
  33. data/lib/bullet/version.rb +1 -1
  34. data/lib/bullet.rb +17 -2
  35. data/spec/bullet/detector/n_plus_one_query_spec.rb +5 -5
  36. data/spec/bullet/detector/unused_eager_loading_spec.rb +3 -1
  37. data/spec/bullet/notification/unused_eager_loading_spec.rb +1 -1
  38. data/spec/bullet/rack_spec.rb +4 -4
  39. data/spec/bullet_spec.rb +43 -0
  40. data/spec/integration/active_record3/association_spec.rb +21 -1
  41. data/spec/integration/active_record4/association_spec.rb +21 -1
  42. data/spec/integration/active_record5/association_spec.rb +21 -1
  43. data/spec/spec_helper.rb +0 -3
  44. data/spec/support/sqlite_seed.rb +1 -0
  45. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f726582290756f07599b35204f8e903fd20350b3
4
- data.tar.gz: 2e4a9e95087d246cb69e887eef07868c2d9e0a63
3
+ metadata.gz: 58f4f616944a1bfde9a34e4670788802f0ccd418
4
+ data.tar.gz: 61aabed03705063018b28e1505f0f0b693e1109b
5
5
  SHA512:
6
- metadata.gz: 66c4b18f8c522a2cfa310bd8b818b177a12507c99255860881d225bac39722f35bfea65d7ea14287496f7fcf4d52d618e77ba712ebb28b2dad7a7a08909f56a8
7
- data.tar.gz: f68a5397786c67ae3aefe57ce3030133f4c0f54a253add872dc54ba83ab00c33439325b6f0ee3500a0534bddca951e95b5929a8dfc0c74d8bf5c818b204992ad
6
+ metadata.gz: 4be86c6d80b67bec48ee84d491b3b92cd19f9b9ea6d6d9d7d973848f93801edf0165f9a7f8f9309d7feee84ed2da1d6f39170161da2d0b01fe8debf7724d6dc9
7
+ data.tar.gz: b82c8e8207775a8e987e52fbbddb6d35350c591df288e1152ee2d55e8de9f257ca55f82bcac02c59807b3cffa76038c0373fc09ba42c36a45be059fc05fed7e8
data/.travis.yml CHANGED
@@ -5,7 +5,7 @@ rvm:
5
5
  - 2.0
6
6
  - 2.1
7
7
  - 2.2
8
- - 2.2.3
8
+ - 2.3.0
9
9
  gemfile:
10
10
  - Gemfile.rails-5.0
11
11
  - Gemfile.rails-4.2
@@ -63,14 +63,14 @@ matrix:
63
63
  gemfile: Gemfile.rails-3.0
64
64
  - rvm: 2.1
65
65
  gemfile: Gemfile.rails-5.0
66
- - rvm: 2.2
67
- gemfile: Gemfile.rails-5.0
68
66
  - rvm: 2.2
69
67
  gemfile: Gemfile.rails-3.0
70
68
  - rvm: 2.2
71
69
  gemfile: Gemfile.rails-3.1
72
70
  - rvm: 2.2
73
71
  gemfile: Gemfile.rails-3.2
72
+ - rvm: 2.2
73
+ gemfile: Gemfile.rails-5.0
74
74
  - rvm: 2.2
75
75
  gemfile: Gemfile.mongoid-3.1
76
76
  - rvm: 2.2
@@ -85,23 +85,23 @@ matrix:
85
85
  gemfile: Gemfile.mongoid-2.5
86
86
  - rvm: 2.2
87
87
  gemfile: Gemfile.mongoid-2.4
88
- - rvm: 2.2.3
88
+ - rvm: 2.3.0
89
89
  gemfile: Gemfile.rails-3.0
90
- - rvm: 2.2.3
90
+ - rvm: 2.3.0
91
91
  gemfile: Gemfile.rails-3.1
92
- - rvm: 2.2.3
92
+ - rvm: 2.3.0
93
93
  gemfile: Gemfile.rails-3.2
94
- - rvm: 2.2.3
94
+ - rvm: 2.3.0
95
95
  gemfile: Gemfile.mongoid-3.1
96
- - rvm: 2.2.3
96
+ - rvm: 2.3.0
97
97
  gemfile: Gemfile.mongoid-3.0
98
- - rvm: 2.2.3
98
+ - rvm: 2.3.0
99
99
  gemfile: Gemfile.mongoid-2.8
100
- - rvm: 2.2.3
100
+ - rvm: 2.3.0
101
101
  gemfile: Gemfile.mongoid-2.7
102
- - rvm: 2.2.3
102
+ - rvm: 2.3.0
103
103
  gemfile: Gemfile.mongoid-2.6
104
- - rvm: 2.2.3
104
+ - rvm: 2.3.0
105
105
  gemfile: Gemfile.mongoid-2.5
106
- - rvm: 2.2.3
106
+ - rvm: 2.3.0
107
107
  gemfile: Gemfile.mongoid-2.4
data/CHANGELOG.md CHANGED
@@ -1,6 +1,24 @@
1
1
  # Next Release
2
2
 
3
- ## 5.1.0 (05/21/2015)
3
+ ## 5.4.0 (10/09/2016)
4
+
5
+ * Support rails 5.1
6
+ * Extract stack trace filtering into module
7
+
8
+ ## 5.3.0 (15/08/2016)
9
+
10
+ * Fix false alert on through association with join sql #301
11
+ * Fix association.target in `through_association` can be singular #302
12
+ * Support `find_by_sql` #303
13
+ * Fix env `REQUEST_URI`
14
+
15
+ ## 5.2.0 (07/26/2016)
16
+
17
+ * Fix `has_cached_counter?` is not defined in HABTM #297
18
+ * Fix false alert if preloaded association has no records #260
19
+ * Support Rails 5.0.0
20
+
21
+ ## 5.1.0 (05/21/2016)
4
22
 
5
23
  * Fix false alert when `empty?` used with `counter_cache`
6
24
  * Fix `alias_method_chain` deprecation for rails 5
@@ -8,7 +26,7 @@
8
26
  * Fix false alert when querying immediately after creation
9
27
  * Fix UnusedEagerLoading bug when multiple eager loading query include same objects
10
28
 
11
- ## 5.0.0 (01/06/2015)
29
+ ## 5.0.0 (01/06/2016)
12
30
 
13
31
  * Support Rails 5.0.0.beta1
14
32
  * Fix `has_many :through` infinite loop issue
data/Gemfile.mongoid-2.4 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 2.4.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.mongoid-2.5 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 2.5.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.mongoid-2.6 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 2.6.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.mongoid-2.7 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 2.7.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.mongoid-2.8 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 2.8.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.mongoid-3.0 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 3.0.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.mongoid-3.1 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 3.1.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.mongoid-4.0 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 4.0.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.mongoid-5.0 CHANGED
@@ -9,8 +9,6 @@ gem 'mongoid', '~> 5.0.0'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/Gemfile.rails-3.0 CHANGED
@@ -10,8 +10,6 @@ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
10
10
 
11
11
  gem "rspec"
12
12
 
13
- gem 'coveralls', require: false
14
-
15
13
  platforms :rbx do
16
14
  gem 'rubysl', '~> 2.0'
17
15
  gem 'rubinius-developer_tools'
data/Gemfile.rails-3.1 CHANGED
@@ -10,8 +10,6 @@ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
10
10
 
11
11
  gem "rspec"
12
12
 
13
- gem 'coveralls', require: false
14
-
15
13
  platforms :rbx do
16
14
  gem 'rubysl', '~> 2.0'
17
15
  gem 'rubinius-developer_tools'
data/Gemfile.rails-3.2 CHANGED
@@ -10,8 +10,6 @@ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
10
10
 
11
11
  gem "rspec"
12
12
 
13
- gem 'coveralls', require: false
14
-
15
13
  platforms :rbx do
16
14
  gem 'rubysl', '~> 2.0'
17
15
  gem 'rubinius-developer_tools'
data/Gemfile.rails-4.0 CHANGED
@@ -10,8 +10,6 @@ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
10
10
 
11
11
  gem "rspec"
12
12
 
13
- gem 'coveralls', require: false
14
-
15
13
  platforms :rbx do
16
14
  gem 'rubysl', '~> 2.0'
17
15
  gem 'rubinius-developer_tools'
data/Gemfile.rails-4.1 CHANGED
@@ -10,8 +10,6 @@ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
10
10
 
11
11
  gem "rspec"
12
12
 
13
- gem 'coveralls', require: false
14
-
15
13
  platforms :rbx do
16
14
  gem 'rubysl', '~> 2.0'
17
15
  gem 'rubinius-developer_tools'
data/Gemfile.rails-4.2 CHANGED
@@ -10,8 +10,6 @@ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
10
10
 
11
11
  gem "rspec"
12
12
 
13
- gem 'coveralls', require: false
14
-
15
13
  platforms :rbx do
16
14
  gem 'rubysl', '~> 2.0'
17
15
  gem 'rubinius-developer_tools'
data/Gemfile.rails-5.0 CHANGED
@@ -2,15 +2,13 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '5.0.0.beta1'
5
+ gem 'rails', '5.0.0'
6
6
  gem 'sqlite3'
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
9
9
 
10
10
  gem "rspec"
11
11
 
12
- gem 'coveralls', require: false
13
-
14
12
  platforms :rbx do
15
13
  gem 'rubysl', '~> 2.0'
16
14
  gem 'rubinius-developer_tools'
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/bullet.png)](http://badge.fury.io/rb/bullet)
4
4
  [![Build Status](https://secure.travis-ci.org/flyerhzm/bullet.png)](http://travis-ci.org/flyerhzm/bullet)
5
- [![Coverage Status](https://coveralls.io/repos/flyerhzm/bullet/badge.png?branch=master)](https://coveralls.io/r/flyerhzm/bullet)
6
5
  <a href="https://codeclimate.com/github/flyerhzm/bullet"><img src="https://codeclimate.com/github/flyerhzm/bullet.png" /></a>
7
6
  [![Coderwall Endorse](http://api.coderwall.com/flyerhzm/endorsecount.png)](http://coderwall.com/flyerhzm)
8
7
 
@@ -63,7 +62,7 @@ config.after_initialize do
63
62
  Bullet.add_footer = true
64
63
  Bullet.stacktrace_includes = [ 'your_gem', 'your_middleware' ]
65
64
  Bullet.stacktrace_excludes = [ 'their_gem', 'their_middleware' ]
66
- Bullet.slack = { webhook_url: 'http://some.slack.url', foo: 'bar' }
65
+ Bullet.slack = { webhook_url: 'http://some.slack.url', channel: '#default', username: 'notifier' }
67
66
  end
68
67
  ```
69
68
 
@@ -238,7 +237,9 @@ Bullet outputs some details info, to enable debug mode, set
238
237
 
239
238
  ## Demo
240
239
 
241
- 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.
240
+ Bullet is designed to function as you browse through your application in development. To see it in action,
241
+ you can visit [https://github.com/flyerhzm/bullet_test](https://github.com/flyerhzm/bullet_test) or
242
+ follow these steps to create, detect, and fix example query problems.
242
243
 
243
244
  1\. Create an example application
244
245
 
@@ -458,4 +459,4 @@ Meanwhile, there's a line appended to `log/bullet.log`
458
459
  Post => [:comments]
459
460
  ```
460
461
 
461
- Copyright (c) 2009 - 2015 Richard Huang (flyerhzm@gmail.com), released under the MIT license
462
+ Copyright (c) 2009 - 2016 Richard Huang (flyerhzm@gmail.com), released under the MIT license
@@ -4,6 +4,25 @@ module Bullet
4
4
 
5
5
  def self.enable
6
6
  require 'active_record'
7
+ ::ActiveRecord::Base.class_eval do
8
+ class <<self
9
+ alias_method :origin_find_by_sql, :find_by_sql
10
+ def find_by_sql(sql)
11
+ result = origin_find_by_sql(sql)
12
+ if Bullet.start?
13
+ if result.is_a? Array
14
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
15
+ Bullet::Detector::CounterCache.add_possible_objects(result)
16
+ elsif result.is_a? ::ActiveRecord::Base
17
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
18
+ Bullet::Detector::CounterCache.add_impossible_object(result)
19
+ end
20
+ end
21
+ result
22
+ end
23
+ end
24
+ end
25
+
7
26
  ::ActiveRecord::Relation.class_eval do
8
27
  alias_method :origin_to_a, :to_a
9
28
  # if select a collection of objects, then these objects have possible to cause N+1 query.
@@ -134,6 +153,16 @@ module Bullet
134
153
  origin_last(*args)
135
154
  end
136
155
 
156
+ alias_method :origin_include?, :include?
157
+ def include?(object)
158
+ if Bullet.start?
159
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
160
+ end
161
+ origin_include?(object)
162
+ end
163
+ end
164
+
165
+ ::ActiveRecord::Associations::HasManyAssociation.class_eval do
137
166
  alias_method :origin_empty?, :empty?
138
167
  def empty?
139
168
  if Bullet.start? && !has_cached_counter?
@@ -141,13 +170,15 @@ module Bullet
141
170
  end
142
171
  origin_empty?
143
172
  end
173
+ end
144
174
 
145
- alias_method :origin_include?, :include?
146
- def include?(object)
175
+ ::ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
176
+ alias_method :origin_empty?, :empty?
177
+ def empty?
147
178
  if Bullet.start?
148
179
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
149
180
  end
150
- origin_include?(object)
181
+ origin_empty?
151
182
  end
152
183
  end
153
184
 
@@ -2,6 +2,25 @@ module Bullet
2
2
  module ActiveRecord
3
3
  def self.enable
4
4
  require 'active_record'
5
+ ::ActiveRecord::Base.class_eval do
6
+ class <<self
7
+ alias_method :origin_find_by_sql, :find_by_sql
8
+ def find_by_sql(sql, binds = [])
9
+ result = origin_find_by_sql(sql, binds)
10
+ if Bullet.start?
11
+ if result.is_a? Array
12
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
13
+ Bullet::Detector::CounterCache.add_possible_objects(result)
14
+ elsif result.is_a? ::ActiveRecord::Base
15
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
16
+ Bullet::Detector::CounterCache.add_impossible_object(result)
17
+ end
18
+ end
19
+ result
20
+ end
21
+ end
22
+ end
23
+
5
24
  ::ActiveRecord::Relation.class_eval do
6
25
  alias_method :origin_to_a, :to_a
7
26
  # if select a collection of objects, then these objects have possible to cause N+1 query.
@@ -116,6 +135,16 @@ module Bullet
116
135
  origin_load_target
117
136
  end
118
137
 
138
+ alias_method :origin_include?, :include?
139
+ def include?(object)
140
+ if Bullet.start?
141
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
142
+ end
143
+ origin_include?(object)
144
+ end
145
+ end
146
+
147
+ ::ActiveRecord::Associations::HasManyAssociation.class_eval do
119
148
  alias_method :origin_empty?, :empty?
120
149
  def empty?
121
150
  if Bullet.start? && !has_cached_counter?(@reflection)
@@ -123,13 +152,15 @@ module Bullet
123
152
  end
124
153
  origin_empty?
125
154
  end
155
+ end
126
156
 
127
- alias_method :origin_include?, :include?
128
- def include?(object)
157
+ ::ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
158
+ alias_method :origin_empty?, :empty?
159
+ def empty?
129
160
  if Bullet.start?
130
161
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
131
162
  end
132
- origin_include?(object)
163
+ origin_empty?
133
164
  end
134
165
  end
135
166
 
@@ -2,6 +2,25 @@ module Bullet
2
2
  module ActiveRecord
3
3
  def self.enable
4
4
  require 'active_record'
5
+ ::ActiveRecord::Base.class_eval do
6
+ class <<self
7
+ alias_method :origin_find_by_sql, :find_by_sql
8
+ def find_by_sql(sql, binds = [])
9
+ result = origin_find_by_sql(sql, binds)
10
+ if Bullet.start?
11
+ if result.is_a? Array
12
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
13
+ Bullet::Detector::CounterCache.add_possible_objects(result)
14
+ elsif result.is_a? ::ActiveRecord::Base
15
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
16
+ Bullet::Detector::CounterCache.add_impossible_object(result)
17
+ end
18
+ end
19
+ result
20
+ end
21
+ end
22
+ end
23
+
5
24
  ::ActiveRecord::Relation.class_eval do
6
25
  alias_method :origin_to_a, :to_a
7
26
  # if select a collection of objects, then these objects have possible to cause N+1 query.
@@ -116,6 +135,16 @@ module Bullet
116
135
  origin_load_target
117
136
  end
118
137
 
138
+ alias_method :origin_include?, :include?
139
+ def include?(object)
140
+ if Bullet.start?
141
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
142
+ end
143
+ origin_include?(object)
144
+ end
145
+ end
146
+
147
+ ::ActiveRecord::Associations::HasManyAssociation.class_eval do
119
148
  alias_method :origin_empty?, :empty?
120
149
  def empty?
121
150
  if Bullet.start? && !has_cached_counter?(@reflection)
@@ -123,13 +152,15 @@ module Bullet
123
152
  end
124
153
  origin_empty?
125
154
  end
155
+ end
126
156
 
127
- alias_method :origin_include?, :include?
128
- def include?(object)
157
+ ::ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
158
+ alias_method :origin_empty?, :empty?
159
+ def empty?
129
160
  if Bullet.start?
130
161
  Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
131
162
  end
132
- origin_include?(object)
163
+ origin_empty?
133
164
  end
134
165
  end
135
166
 
@@ -2,6 +2,25 @@ module Bullet
2
2
  module ActiveRecord
3
3
  def self.enable
4
4
  require 'active_record'
5
+ ::ActiveRecord::Base.class_eval do
6
+ class <<self
7
+ alias_method :origin_find_by_sql, :find_by_sql
8
+ def find_by_sql(sql, binds = [])
9
+ result = origin_find_by_sql(sql, binds)
10
+ if Bullet.start?
11
+ if result.is_a? Array
12
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
13
+ Bullet::Detector::CounterCache.add_possible_objects(result)
14
+ elsif result.is_a? ::ActiveRecord::Base
15
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
16
+ Bullet::Detector::CounterCache.add_impossible_object(result)
17
+ end
18
+ end
19
+ result
20
+ end
21
+ end
22
+ end
23
+
5
24
  ::ActiveRecord::Relation.class_eval do
6
25
  alias_method :origin_to_a, :to_a
7
26
  # if select a collection of objects, then these objects have possible to cause N+1 query.
@@ -18,6 +18,21 @@ module Bullet
18
18
  end
19
19
  result
20
20
  end
21
+
22
+ alias_method :origin_find_by_sql, :find_by_sql
23
+ def find_by_sql(sql, binds = [])
24
+ result = origin_find_by_sql(sql, binds)
25
+ if Bullet.start?
26
+ if result.is_a? Array
27
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
28
+ Bullet::Detector::CounterCache.add_possible_objects(result)
29
+ elsif result.is_a? ::ActiveRecord::Base
30
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
31
+ Bullet::Detector::CounterCache.add_impossible_object(result)
32
+ end
33
+ end
34
+ result
35
+ end
21
36
  end
22
37
  end
23
38
 
@@ -96,6 +111,7 @@ module Bullet
96
111
 
97
112
  ::ActiveRecord::Associations::JoinDependency.class_eval do
98
113
  alias_method :origin_instantiate, :instantiate
114
+ alias_method :origin_construct, :construct
99
115
  alias_method :origin_construct_model, :construct_model
100
116
 
101
117
  def instantiate(result_set, aliases)
@@ -111,6 +127,27 @@ module Bullet
111
127
  records
112
128
  end
113
129
 
130
+ def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
131
+ if Bullet.start?
132
+ unless ar_parent.nil?
133
+ parent.children.each do |node|
134
+ key = aliases.column_alias(node, node.primary_key)
135
+ id = row[key]
136
+ if id.nil?
137
+ associations = node.reflection.name
138
+ Bullet::Detector::Association.add_object_associations(ar_parent, associations)
139
+ Bullet::Detector::NPlusOneQuery.call_association(ar_parent, associations)
140
+ @bullet_eager_loadings[ar_parent.class] ||= {}
141
+ @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
142
+ @bullet_eager_loadings[ar_parent.class][ar_parent] << associations
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ origin_construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
149
+ end
150
+
114
151
  # call join associations
115
152
  def construct_model(record, node, row, model_cache, id, aliases)
116
153
  result = origin_construct_model(record, node, row, model_cache, id, aliases)