bullet 6.1.5 → 7.0.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
  SHA256:
3
- metadata.gz: b21c2c4ca3caf6c41961a7182a5c8d37f6b89aa78b8dfb7badfb940f11a23191
4
- data.tar.gz: 0f432034f9b4cb2fe6c6572481c797aefcfa69373839fbd0985a7efd2a0bbea9
3
+ metadata.gz: 6fbdfd6fe2f412c6632b877352fdf912b56fd54e255101dc16ae414a218fc2ee
4
+ data.tar.gz: 0a765e969ccae1ef685051350324052225fea00e80d7d37a6b8cce6d8ad1f28e
5
5
  SHA512:
6
- metadata.gz: d2457987f11f034fa457030cf7161d7508fb26230cf9e88a2571c54a934ad9a1330b48dd3d38eede3033bd7ef6c920e564dcbfa43a15354bf72d14ed799aefe2
7
- data.tar.gz: ed6690fcb3bd778d6d5a27538a0ee78d298c749be1e445c305b9884448ca13f97e5a62c76ac48229a250041bb09ba609d6b154b12cf42a0f3dca66fbb9c83021
6
+ metadata.gz: 35c561cc6534f355a56d1aa0e880bb51941c126ce8a9c704bbc8c0f59c67cf5890a00d650919d5a458a913f4d6a125b17e57c92130d48baa9b6a90db190db763
7
+ data.tar.gz: 4f29d4316862401ad1d5d4edfdf21f6f8045a37e21acc4d12f3cdd80e528b12924a9f0a2ab5fdb366432ea5c8e656210887112fc338da8539a34586da88710e9
@@ -64,3 +64,19 @@ jobs:
64
64
  bundler-cache: true
65
65
  - name: Run tests
66
66
  run: bundle exec rake
67
+ test_rails_7:
68
+ runs-on: ubuntu-latest
69
+ strategy:
70
+ matrix:
71
+ gemfile: ['Gemfile.rails-7.0']
72
+ env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
73
+ BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}
74
+ steps:
75
+ - uses: actions/checkout@v2
76
+ - name: Set up Ruby
77
+ uses: ruby/setup-ruby@v1
78
+ with:
79
+ ruby-version: 3.0
80
+ bundler-cache: true
81
+ - name: Run tests
82
+ run: bundle exec rake
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## Next Release
2
2
 
3
+ ## 7.0.0 (12/18/2021)
4
+
5
+ * Support rails 7
6
+ * Fix Mongoid 7 view iteration
7
+ * Move CI from Travis to Github Actions
8
+
3
9
  ## 6.1.5 (08/16/2021)
4
10
 
5
11
  * Rename whitelist to safelist
data/Gemfile.rails-7.0 ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'rails', '~> 7.0.0'
6
+ gem 'sqlite3'
7
+ gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
+ gem 'activerecord-import'
9
+
10
+ gem "rspec"
@@ -75,23 +75,6 @@ module Bullet
75
75
  end
76
76
  )
77
77
 
78
- ::ActiveRecord::FinderMethods.prepend(
79
- Module.new do
80
- # add includes in scope
81
- def find_with_associations
82
- return super { |r| yield r } if block_given?
83
-
84
- records = super
85
- if Bullet.start?
86
- associations = (eager_load_values + includes_values).uniq
87
- records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
88
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
89
- end
90
- records
91
- end
92
- end
93
- )
94
-
95
78
  ::ActiveRecord::Associations::JoinDependency.prepend(
96
79
  Module.new do
97
80
  def instantiate(result_set, &block)
@@ -149,6 +132,17 @@ module Bullet
149
132
  end
150
133
  )
151
134
 
135
+ ::ActiveRecord::Associations::Association.prepend(
136
+ Module.new do
137
+ def inversed_from(record)
138
+ if Bullet.start?
139
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
140
+ end
141
+ super
142
+ end
143
+ end
144
+ )
145
+
152
146
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
153
147
  Module.new do
154
148
  def load_target
@@ -102,23 +102,6 @@ module Bullet
102
102
  end
103
103
  )
104
104
 
105
- ::ActiveRecord::FinderMethods.prepend(
106
- Module.new do
107
- # add includes in scope
108
- def find_with_associations
109
- return super { |r| yield r } if block_given?
110
-
111
- records = super
112
- if Bullet.start?
113
- associations = (eager_load_values + includes_values).uniq
114
- records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
115
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
116
- end
117
- records
118
- end
119
- end
120
- )
121
-
122
105
  ::ActiveRecord::Associations::JoinDependency.prepend(
123
106
  Module.new do
124
107
  def instantiate(result_set, &block)
@@ -176,6 +159,17 @@ module Bullet
176
159
  end
177
160
  )
178
161
 
162
+ ::ActiveRecord::Associations::Association.prepend(
163
+ Module.new do
164
+ def inversed_from(record)
165
+ if Bullet.start?
166
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
167
+ end
168
+ super
169
+ end
170
+ end
171
+ )
172
+
179
173
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
180
174
  Module.new do
181
175
  def load_target
@@ -102,23 +102,6 @@ module Bullet
102
102
  end
103
103
  )
104
104
 
105
- ::ActiveRecord::FinderMethods.prepend(
106
- Module.new do
107
- # add includes in scope
108
- def find_with_associations
109
- return super { |r| yield r } if block_given?
110
-
111
- records = super
112
- if Bullet.start?
113
- associations = (eager_load_values + includes_values).uniq
114
- records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
115
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
116
- end
117
- records
118
- end
119
- end
120
- )
121
-
122
105
  ::ActiveRecord::Associations::JoinDependency.prepend(
123
106
  Module.new do
124
107
  def instantiate(result_set, strict_loading_value, &block)
@@ -176,6 +159,17 @@ module Bullet
176
159
  end
177
160
  )
178
161
 
162
+ ::ActiveRecord::Associations::Association.prepend(
163
+ Module.new do
164
+ def inversed_from(record)
165
+ if Bullet.start?
166
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
167
+ end
168
+ super
169
+ end
170
+ end
171
+ )
172
+
179
173
  ::ActiveRecord::Associations::CollectionAssociation.prepend(
180
174
  Module.new do
181
175
  def load_target
@@ -0,0 +1,261 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module SaveWithBulletSupport
5
+ def _create_record(*)
6
+ super do
7
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
8
+ yield(self) if block_given?
9
+ end
10
+ end
11
+ end
12
+
13
+ module ActiveRecord
14
+ def self.enable
15
+ require 'active_record'
16
+ ::ActiveRecord::Base.extend(
17
+ Module.new do
18
+ def find_by_sql(sql, binds = [], preparable: nil, &block)
19
+ result = super
20
+ if Bullet.start?
21
+ if result.is_a? Array
22
+ if result.size > 1
23
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
24
+ Bullet::Detector::CounterCache.add_possible_objects(result)
25
+ elsif result.size == 1
26
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
27
+ Bullet::Detector::CounterCache.add_impossible_object(result.first)
28
+ end
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
36
+ end
37
+ )
38
+
39
+ ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
40
+
41
+ ::ActiveRecord::Relation.prepend(
42
+ Module.new do
43
+ # if select a collection of objects, then these objects have possible to cause N+1 query.
44
+ # if select only one object, then the only one object has impossible to cause N+1 query.
45
+ def records
46
+ result = super
47
+ if Bullet.start?
48
+ if result.first.class.name !~ /^HABTM_/
49
+ if result.size > 1
50
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
51
+ Bullet::Detector::CounterCache.add_possible_objects(result)
52
+ elsif result.size == 1
53
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
54
+ Bullet::Detector::CounterCache.add_impossible_object(result.first)
55
+ end
56
+ end
57
+ end
58
+ result
59
+ end
60
+ end
61
+ )
62
+
63
+ ::ActiveRecord::Associations::Preloader::Branch.prepend(
64
+ Module.new do
65
+ def preloaders_for_reflection(reflection, reflection_records)
66
+ if Bullet.start?
67
+ reflection_records.compact!
68
+ if reflection_records.first.class.name !~ /^HABTM_/
69
+ reflection_records.each { |record| Bullet::Detector::Association.add_object_associations(record, reflection.name) }
70
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
71
+ end
72
+ end
73
+ super
74
+ end
75
+ end
76
+ )
77
+
78
+ ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
79
+ Module.new do
80
+ def preloaded_records
81
+ if Bullet.start? && !defined?(@preloaded_records)
82
+ source_preloaders.each do |source_preloader|
83
+ reflection_name = source_preloader.send(:reflection).name
84
+ source_preloader.send(:owners).each do |owner|
85
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
86
+ end
87
+ end
88
+ end
89
+ super
90
+ end
91
+ end
92
+ )
93
+
94
+ ::ActiveRecord::Associations::JoinDependency.prepend(
95
+ Module.new do
96
+ def instantiate(result_set, strict_loading_value, &block)
97
+ @bullet_eager_loadings = {}
98
+ records = super
99
+
100
+ if Bullet.start?
101
+ @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
102
+ objects = eager_loadings_hash.keys
103
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
104
+ objects,
105
+ eager_loadings_hash[objects.first].to_a
106
+ )
107
+ end
108
+ end
109
+ records
110
+ end
111
+
112
+ def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
113
+ if Bullet.start?
114
+ unless ar_parent.nil?
115
+ parent.children.each do |node|
116
+ key = aliases.column_alias(node, node.primary_key)
117
+ id = row[key]
118
+ next unless id.nil?
119
+
120
+ associations = node.reflection.name
121
+ Bullet::Detector::Association.add_object_associations(ar_parent, associations)
122
+ Bullet::Detector::NPlusOneQuery.call_association(ar_parent, associations)
123
+ @bullet_eager_loadings[ar_parent.class] ||= {}
124
+ @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
125
+ @bullet_eager_loadings[ar_parent.class][ar_parent] << associations
126
+ end
127
+ end
128
+ end
129
+
130
+ super
131
+ end
132
+
133
+ # call join associations
134
+ def construct_model(record, node, row, model_cache, id, strict_loading_value)
135
+ result = super
136
+
137
+ if Bullet.start?
138
+ associations = node.reflection.name
139
+ Bullet::Detector::Association.add_object_associations(record, associations)
140
+ Bullet::Detector::NPlusOneQuery.call_association(record, associations)
141
+ @bullet_eager_loadings[record.class] ||= {}
142
+ @bullet_eager_loadings[record.class][record] ||= Set.new
143
+ @bullet_eager_loadings[record.class][record] << associations
144
+ end
145
+
146
+ result
147
+ end
148
+ end
149
+ )
150
+
151
+ ::ActiveRecord::Associations::Association.prepend(
152
+ Module.new do
153
+ def inversed_from(record)
154
+ if Bullet.start?
155
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
156
+ end
157
+ super
158
+ end
159
+ end
160
+ )
161
+
162
+ ::ActiveRecord::Associations::CollectionAssociation.prepend(
163
+ Module.new do
164
+ def load_target
165
+ records = super
166
+
167
+ if Bullet.start?
168
+ if is_a? ::ActiveRecord::Associations::ThroughAssociation
169
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
170
+ association = owner.association(reflection.through_reflection.name)
171
+ Array(association.target).each do |through_record|
172
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
173
+ end
174
+
175
+ if reflection.through_reflection != through_reflection
176
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
177
+ end
178
+ end
179
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
180
+ if records.first.class.name !~ /^HABTM_/
181
+ if records.size > 1
182
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
183
+ Bullet::Detector::CounterCache.add_possible_objects(records)
184
+ elsif records.size == 1
185
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
186
+ Bullet::Detector::CounterCache.add_impossible_object(records.first)
187
+ end
188
+ end
189
+ end
190
+ records
191
+ end
192
+
193
+ def empty?
194
+ if Bullet.start? && !reflection.has_cached_counter?
195
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
196
+ end
197
+ super
198
+ end
199
+
200
+ def include?(object)
201
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
202
+ super
203
+ end
204
+ end
205
+ )
206
+
207
+ ::ActiveRecord::Associations::SingularAssociation.prepend(
208
+ Module.new do
209
+ # call has_one and belongs_to associations
210
+ def reader
211
+ result = super
212
+
213
+ if Bullet.start?
214
+ if owner.class.name !~ /^HABTM_/
215
+ if is_a? ::ActiveRecord::Associations::ThroughAssociation
216
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
217
+ association = owner.association(reflection.through_reflection.name)
218
+ Array(association.target).each do |through_record|
219
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
220
+ end
221
+
222
+ if reflection.through_reflection != through_reflection
223
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
224
+ end
225
+ end
226
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
227
+
228
+ if Bullet::Detector::NPlusOneQuery.impossible?(owner)
229
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
230
+ else
231
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
232
+ end
233
+ end
234
+ end
235
+ result
236
+ end
237
+ end
238
+ )
239
+
240
+ ::ActiveRecord::Associations::HasManyAssociation.prepend(
241
+ Module.new do
242
+ def empty?
243
+ result = super
244
+ if Bullet.start? && !reflection.has_cached_counter?
245
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
246
+ end
247
+ result
248
+ end
249
+
250
+ def count_records
251
+ result = reflection.has_cached_counter?
252
+ if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
253
+ Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
254
+ end
255
+ super
256
+ end
257
+ end
258
+ )
259
+ end
260
+ end
261
+ end
@@ -29,6 +29,8 @@ module Bullet
29
29
  'active_record60'
30
30
  elsif active_record61?
31
31
  'active_record61'
32
+ elsif active_record70?
33
+ 'active_record70'
32
34
  else
33
35
  raise "Bullet does not support active_record #{::ActiveRecord::VERSION::STRING} yet"
34
36
  end
@@ -64,6 +66,10 @@ module Bullet
64
66
  active_record? && ::ActiveRecord::VERSION::MAJOR == 6
65
67
  end
66
68
 
69
+ def active_record7?
70
+ active_record? && ::ActiveRecord::VERSION::MAJOR == 7
71
+ end
72
+
67
73
  def active_record40?
68
74
  active_record4? && ::ActiveRecord::VERSION::MINOR == 0
69
75
  end
@@ -96,6 +102,10 @@ module Bullet
96
102
  active_record6? && ::ActiveRecord::VERSION::MINOR == 1
97
103
  end
98
104
 
105
+ def active_record70?
106
+ active_record7? && ::ActiveRecord::VERSION::MINOR == 0
107
+ end
108
+
99
109
  def mongoid4x?
100
110
  mongoid? && ::Mongoid::VERSION =~ /\A4/
101
111
  end
@@ -23,16 +23,33 @@ module Bullet
23
23
  end
24
24
 
25
25
  def each(&block)
26
- return to_enum unless block
27
-
28
- records = []
29
- origin_each { |record| records << record }
30
- if records.length > 1
31
- Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
32
- elsif records.size == 1
33
- Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
26
+ return to_enum unless block_given?
27
+
28
+ first_document = nil
29
+ document_count = 0
30
+
31
+ origin_each do |document|
32
+ document_count += 1
33
+
34
+ if document_count == 1
35
+ first_document = document
36
+ elsif document_count == 2
37
+ Bullet::Detector::NPlusOneQuery.add_possible_objects([first_document, document])
38
+ yield(first_document)
39
+ first_document = nil
40
+ yield(document)
41
+ else
42
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(document)
43
+ yield(document)
44
+ end
34
45
  end
35
- records.each(&block)
46
+
47
+ if document_count == 1
48
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(first_document)
49
+ yield(first_document)
50
+ end
51
+
52
+ self
36
53
  end
37
54
 
38
55
  def eager_load(docs)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bullet
4
- VERSION = '6.1.5'
4
+ VERSION = '7.0.0'
5
5
  end
@@ -28,7 +28,7 @@ if !mongoid? && active_record?
28
28
  expect(Bullet.collected_counter_cache_notifications).to be_empty
29
29
  end
30
30
 
31
- if active_record5? || active_record6?
31
+ if ActiveRecord::VERSION::MAJOR > 4
32
32
  it 'should not need counter cache for has_many through' do
33
33
  Client.all.each { |client| client.firms.size }
34
34
  expect(Bullet.collected_counter_cache_notifications).to be_empty
data/test.sh CHANGED
@@ -1,5 +1,6 @@
1
1
  #bundle update rails && bundle exec rspec spec
2
2
  #BUNDLE_GEMFILE=Gemfile.mongoid bundle update mongoid && BUNDLE_GEMFILE=Gemfile.mongoid bundle exec rspec spec
3
+ BUNDLE_GEMFILE=Gemfile.rails-7.0 bundle && BUNDLE_GEMFILE=Gemfile.rails-7.0 bundle exec rspec spec
3
4
  BUNDLE_GEMFILE=Gemfile.rails-6.1 bundle && BUNDLE_GEMFILE=Gemfile.rails-6.1 bundle exec rspec spec
4
5
  BUNDLE_GEMFILE=Gemfile.rails-6.0 bundle && BUNDLE_GEMFILE=Gemfile.rails-6.0 bundle exec rspec spec
5
6
  BUNDLE_GEMFILE=Gemfile.rails-5.2 bundle && BUNDLE_GEMFILE=Gemfile.rails-5.2 bundle exec rspec spec
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: 6.1.5
4
+ version: 7.0.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: 2021-08-16 00:00:00.000000000 Z
11
+ date: 2021-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -63,6 +63,7 @@ files:
63
63
  - Gemfile.rails-5.2
64
64
  - Gemfile.rails-6.0
65
65
  - Gemfile.rails-6.1
66
+ - Gemfile.rails-7.0
66
67
  - Guardfile
67
68
  - Hacking.md
68
69
  - MIT-LICENSE
@@ -78,6 +79,7 @@ files:
78
79
  - lib/bullet/active_record52.rb
79
80
  - lib/bullet/active_record60.rb
80
81
  - lib/bullet/active_record61.rb
82
+ - lib/bullet/active_record70.rb
81
83
  - lib/bullet/bullet_xhr.js
82
84
  - lib/bullet/dependency.rb
83
85
  - lib/bullet/detector.rb