bullet 6.1.5 → 7.0.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.
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